Commit Graph

154 Commits

Author SHA1 Message Date
Mark Lacey
a4a6c0d5e0 Clean-up solver state management for a constraint system.
Make SolverState manage whether the ConstraintSystem it belongs to has a
current SolverState.

Also a couple minor formatting fixes for ternary expressions involving
solverState.
2016-11-15 17:06:20 -08:00
Mark Lacey
fbbd8346d0 Small control-flow simplifications, NFC.
Simplify some control-flow to reduce indentation and eliminate an
unneeded flag variable.

Also update a comment to match the code that went in with
b5500b8600.
2016-11-15 09:20:40 -08:00
swift-ci
0029ba22f3 Merge pull request #5785 from rudkx/minor-cleanup 2016-11-14 22:57:19 -08:00
Mark Lacey
8b2bfcb442 Refactor a couple functions out of solveSimplified().
These are both logical bits of code that deserve first-class function status.
2016-11-14 22:14:10 -08:00
Mark Lacey
3ff07ab031 Remove extra calls to getRepresentative().
The calls to simplifyType() already return the representative if it exists.
2016-11-14 21:56:12 -08:00
practicalswift
38351faefc [gardening] Fix recently introduced typos 2016-11-11 18:35:01 +01:00
Doug Gregor
e20464a02c [Constraint solver] Remove 'type member' constraint.
Only some fallback code in the for-each binding checking code was
using this constraint. Implement those checks more directly.
2016-11-06 23:14:15 -08:00
Doug Gregor
ba06709eca [Constraint solver] Dependent members don't "involve type variables".
The constraint solver tries not to solve for type variables that
"involve other type variables", which handles the case where we have
seen a constraint that mentions the type variable under consideration
as well as a different type variable, but in a constraint that we
cannot capture in a binding. Solving for such type variables too early
can lead to missed solutions, so we avoid it.

Tweak the logic for this computation to not consider type variables
mentioned within dependent member types (e.g., $T0.Iterator.Element),
because such types do not affect type inference at all, and therefore
shouldn't prevent solving for the type variable in question.
2016-11-05 23:20:28 -07:00
Doug Gregor
522cbf26fa [Constraint solver] Show potential bindings in debug output. 2016-11-05 23:20:28 -07:00
Doug Gregor
f168e7270c [Type checker] Use DependentMemberType instead of type variables for nested types.
In the constraint solver, we've traditionally modeled nested type via
a "type member" constraint of the form

  $T1 = $T0.NameOfTypeMember

and treated $T1 as a type variable. While the solver did generally try
to avoid attempting bindings for $T1 (it would wait until $T0 was
bound, which solves the constraint), on occasion we would get weird
behavior because the solver did try to bind the type
variable.

With this commit, model nested types via DependentMemberType, the same
way we handle (e.g.) the nested type of a generic type parameter. This
solution maintains more information (e.g., we know specifically which
associated type we're referring to), fits in better with the type
system (we know how to deal with dependent members throughout the type
checker, AST, and so on), and is easier to reason able.

This change is a performance optimization for the type checker for a
few reasons. First, it reduces the number of type variables we need to
deal with significantly (we create half as many type variables while
type checking the standard library), and the solver scales poorly with
the number of type variables because it visits all of the
as-yet-unbound type variables at each solving step. Second, it
eliminates a number of redundant by-name lookups in cases where we
already know which associated type we want.

Overall, this change provides a 25% speedup when type-checking the
standard library.
2016-11-05 23:20:28 -07:00
Doug Gregor
245f995b5d [Constraint solver] Track the total number of type variables created.
The constraint solver scales poorly with the number of type variables,
so track it.
2016-11-05 23:20:27 -07:00
Mark Lacey
12cf13de8e Remove dead code related to tracking favored constraints.
At one point this was added in order to inhibit some bridging
conversions while we are handling favored constraints, but that code has
been removed now, making this dead.

Noticed by inspection.
2016-10-31 11:44:25 -07:00
Doug Gregor
33ad7a8473 [Constraint solver] Remove erroneous constraints from the constraint graph.
When a constraint fails, we retire it... but we also need to remove it
from the constraint graph. Otherwise, we break invariants when
diagnostic generation attempts to continue simplification.

Fixes rdar://rdar28145033.
2016-10-27 21:35:14 -07:00
Doug Gregor
c58aafdce5 [Constraint solver] Unify the two typeVarOccursInType implementations.
NFC, thanks @CodaFi!
2016-10-25 14:13:31 -07:00
Doug Gregor
a65812c558 [Constraint solver] Add ConstraintKind::BindToPointerType.
This matches up with TypeMatchKind::BindToPointerType.
2016-10-24 21:24:49 -07:00
Doug Gregor
419fb80910 [Constraint solver] Only add defaultable types on the actual type variable.
When adding a defaultable type, make sure that the type being
defaulted is actually the type variable.
2016-10-24 13:06:25 -07:00
Doug Gregor
b69d01eef2 [Constraint solver] Remove unused 'class' constraints. NFC
We're not using these now. Someday, maybe, but it will be easy to
bring back this code if we find that we need it later.
2016-10-21 14:03:56 -07:00
Doug Gregor
483dfdcaa1 [Constraint solver] Remove 'archetype' constraint kind. NFC
Archetype constraints haven't been needed since we implemented SE-0091.
2016-10-21 14:03:56 -07:00
Doug Gregor
a7a13b6c4f [Constraint solver] Don't bail out early when we have equivalent type variables.
Found by inspection; a misplaced 'break' meant that, if we encountered
a relational constraint where both sides are type variables that are
equivalent, we would stop looking for more type bindings, which could
lead us to miss obvious type inferences. While I wasn't able to
construct a case where this changed the behavior of type inference,
this *does* happen, and the previous code was clearly wrong.
2016-10-20 10:36:02 -07:00
Doug Gregor
3d6de63b4f [Type checker] Don't use default literal types for normal conformance constraints
We previously allowed *any* conformance constraint to an
ExpressibleBy*Literal protocol to provide a default type (e.g.,
Int/Double/String/etc.) based on the kind of literal protocol. This
led to weird type inference behavior. Restrict the defaulting to
actual literals---not just conformances to literal protocols---which
is a much more reasonable rule.

Because this is a source-breaking change, only introduce this new
behavior when the Swift version >= 4, maintaining the old behavior in
Swift 3 compatibility mode.
2016-10-20 10:36:02 -07:00
Doug Gregor
4b9adae8ae [Constraint Solver] Don't perform a join when we've adjusted an IUO to optional.
Fixes rdar://problem/28621624, an intentional source-breaking change
from Swift 3.
2016-10-19 16:08:08 -07:00
Doug Gregor
49b833b51a [Type checker] Eliminate the 'literalConformanceProto' state on type variables.
The 'literalConformanceProto' field of
TypeVariableType::Implementation didn't take into account equivalence
classes of type variables. Eliminate it, and either look at the actual
expressions (for optimizing constraints during constraint generation)
or the actual constraints on a given type variable (for determining
whether to include optionals in the set of potential type variable
bindings).

(cherry picked from commit 6bdd9cfae5)
2016-10-13 16:22:01 -07:00
Doug Gregor
01fa24cc9b Speculatively revert "[Type checker] Eliminate the 'literalConformanceProto' state on type variables."
This reverts commit 6bdd9cfae5. This
commit *appears* to be breaking something in Dollar involving
inference with array literals and 'nil'; pull it back for more
investigation.
2016-10-12 09:20:16 -07:00
Doug Gregor
6bdd9cfae5 [Type checker] Eliminate the 'literalConformanceProto' state on type variables.
The 'literalConformanceProto' field of
TypeVariableType::Implementation didn't take into account equivalence
classes of type variables. Eliminate it, and either look at the actual
expressions (for optimizing constraints during constraint generation)
or the actual constraints on a given type variable (for determining
whether to include optionals in the set of potential type variable
bindings).
2016-10-11 17:09:13 -07:00
Doug Gregor
331937a129 [Type checker] Track defaulted constraints based on their locator. NFC
While, tracking defaulted constraints based on their type variable
usually works in practice, it can break if the type variable ends up
being equivalent to some other type variable that. Instead, record the
locators associated with Defaultable constraints where we used the
default, which are easier to work with during constraint application.
2016-10-11 17:09:13 -07:00
Doug Gregor
c2b9759cd3 Simplify ConstraintSystem::getFixedTypeRecursive and use it consistently.
We had a few places that were performing ad hoc variants of
ConstraintSystem::getFixedTypeRecursive(); simplify it's interface so
we can use it everywhere consistently. Fixes rdar://problem/27261929.
2016-10-11 17:08:52 -07:00
Doug Gregor
50341da32b Use "TypeBase::hasError()" rather than "is<ErrorType>()" where needed.
In most places where we were checking "is<ErrorType>()", we now mean
"any error occurred". The few exceptions are in associated type
inference, code completion, and expression diagnostics, where we might
still work with partial errors.
2016-10-07 10:58:23 -07:00
Doug Gregor
66e20116f2 Extend ErrorType with an "original type" and use it to clean up substitution.
Type::subst()'s "IgnoreMissing" option was fairly unprincipled, dropping
unsubstituted types into the resulting AST without any indication
whatsoever that anything went wrong. Replace this notion with a new
form of ErrorType that explicitly tracks which substituted type caused
the problem. It's still an ErrorType, but it prints like the
substituted type (which is important for code completion) and allows
us to step back to the substituted type if needed (which is used by
associated type inference). Then, allow Type::subst(), when the new
UseErrorTypes flag is passed, to form partially-substituted types that
contain errors, which both code completion and associated type
inference relied on.

Over time, I hope we can use error-types-with-original-types more
often to eliminate "<<error type>>" from diagnostics and teach
Type::subst() never to return a "null" type. Clients can check
"hasError()" to deal with failure cases rather than checking null.
2016-10-06 16:40:28 -07:00
practicalswift
7c63623ffc [gardening] Fix 13 recently introduced typos. 2016-09-16 20:30:57 +02:00
Pavel Yaskevich
73318a2132 [Type Checker] Extend Path Consistency algorithm to cover collections
ExprCollector is extended to cover all generic collections instead of
only dictionary expressions. Contextual type propagation is extended
to support partial solving of collections embedded into coerce expressions.
2016-09-14 13:51:08 -07:00
Erik Eckstein
38cb48b29a Revert "[Type Checker] Extend Path Consistency algorithm to cover collections"
This reverts commit f590a1ba03.

It breaks this kind of code:

test.swift:2:34: error: cannot convert value of type 'Int' to expected element type 'UInt32'
 let lengthBytes: [UInt32] = [55 * 8, 0]
                              ~~~^~~
                              UInt32( )
2016-09-14 11:15:34 -07:00
Pavel Yaskevich
f590a1ba03 [Type Checker] Extend Path Consistency algorithm to cover collections
ExprCollector is extended to cover all generic collections instead of
only dictionary expressions. Contextual type propagation is extended
to support partial solving of collections embedded into coerce expressions.
2016-09-13 01:34:14 -07:00
Pavel Yaskevich
99ac807e9e [Type Checker] replace std::{stack, queue} with llvm::SmallVector 2016-09-13 00:37:40 -07:00
Rintaro Ishizaki
339387e95b [AST] Remove DefaultValueExpr type (#4713)
The last instantiation of this type was removed in 68bcb0d2af
2016-09-12 16:50:02 +09:00
Mark Lacey
37041f1557 Fix typos. 2016-09-01 14:28:12 -07:00
Pavel Yaskevich
2011e502ad [Type Checker] Prevent Path Consistency algorithm from aborting too aggressively
Instead of failing shrinking when there are no solutions for current
sub-expression, let's restore overload domains for previously solved
sub-expressions and move on trying to solve next expression in the queue.
2016-08-26 17:21:04 -07:00
Pavel Yaskevich
8e04a84239 [Type checker] Introduce directional path consistency algorithm
DPC algorithm tries to solve individual sub-expressions and combine
resolved types as a way to reduce pre-existing OSR domains. Solving
is done bottom-up so each consecutive sub-expression tightens
possible solution domain even further.
2016-08-24 18:40:28 -07:00
Mishal Shah
a84704f4b5 Revert "[Type checker] Introduce directional path consistency algorithm" 2016-08-24 17:53:12 -07:00
Pavel Yaskevich
de51b01195 [Type checker] Introduce directional path consistency algorithm
DPC algoritm tries to solve individual sub-expressions and combine
resolved types as a way to reduce pre-existing OSR domains. Solving
is done bottom-up so each consecutive sub-expression tightens
possible solution domain even further.
2016-08-24 14:38:46 -07:00
Doug Gregor
51529ae888 Eliminate the -enable-id-as-any flag; it's always on now anyway.
Simplify e.g., ASTContext::getBridgedToObjC(), which no longer needs
the optional return.

Eliminate the now-unused constraint kind for checking bridging to
Objective-C.
2016-08-19 21:17:09 -07:00
Doug Gregor
4d77a1fbf1 [Type checker] Strip unused code from enumerateDirectSupertypes.
The goal is to progressively remove everything from this function so
it can be removed entirely. It's an awful hack.
2016-08-19 13:24:13 -07:00
Doug Gregor
78b7bb4c4b [Type checker]: Implement 'join' for optional types and a special case for 'nil'.
The join operation for optional types is straightforward to define/implement:

  join(T?, U)  ::= join(T, U)?
  join(T, U?)  ::= join(T, U)?
  join(T?, U?) ::= join(T, U)?

As a special case in the constraint solver, handle the join of a 'nil'
literal with a non-ExpressibleByNilLiteral-conforming concrete type
'T' to produce 'T?'. This allows us, e.g., infer [String?] for the
expressions

  ["hello", nil]

and

   true ? "hello" nil

for example. Fixes rdar://problem/16326914.
2016-08-19 10:46:59 -07:00
Doug Gregor
1b99f7f5d5 [Type checker] s/meet/join, so we get our terminology straight. 2016-08-19 10:46:59 -07:00
Doug Gregor
22287ddb58 [Type system] Infer 'Any' for array elements and dictionary values and 'AnyHashable' for dictionary keys.
The id-as-Any work regressed cases where Swift code could specify
heterogeneous collection literals, e.g.,

    var states: [String: Any] = [
      "California": [
        "population": 37_000_000,
        "cities": ["Los Angeles", "San Diego", "San Jose"],
      ],
      "Oregon": [
        "population": 4_000_000,
        "cities": ["Portland", "Salem", "Eugene"],
      ]
    ]

Prior to this, the code worked (when Foundation was imported) because
we'd end up with literals of type [NSObject : AnyObject].

The new defaulting rule says that the element type of an array literal
and the key/value types of a dictionary literal can be defaulted if no
stronger type can be inferred. The default type is:

  Any, for the element type of an array literal or the value type of a
  dictionary literal, or

  AnyHashable, for the key type of a dictionary literal.

The latter is intended to compose with implicit conversions to
AnyHashable, so the most-general inferred dictionary type is
[AnyHashable : Any] and will work for any plausible dictionary
literal.

To prevent this inference from diluting types too greatly, we don't
allow this inference in "top-level" expressions, e.g.,

  let d = ["a" : 1, "b" : "two"]

will produce an error because it's a heterogeneous dictionary literal
at the top level. One should annotate this with, e.g.,

  let d = ["a" : 1, "b" : "two"] as [String : Any]

However, we do permit heterogeneous collections in nested positions,
to support cases like the original motivating example.

Fixes rdar://problem/27661580.
2016-08-04 20:58:13 -07:00
Doug Gregor
2bcf555896 [Constraint solver] Introduce a *trivial* 'meet' operation for types.
Stub out a simplistic 'meet' operation for types that currently only
handles finding the meet of two class types. Use it to optimize the
constraint solver ever so slightly: when we see a type variable whose
constraints state that it is a supertype of two different concrete
types, we attempt to compute their meet and, if we find it, only
produce one potential binding that is the meet itself.

Note that this is an extremely poor implementation of this concept
that is meant to address a specific regression being introduced by the
defaulting of collection literal element types. A real implementation
would, at the very least:

* Implement a proper 'meet' that covers all subtyping in the language.
* Distinguish between "I don't know if there is a meet" and "I am
  absolutely certain that there is no meet".
* Collapse the constraints themselves to reduce the number of
  constraints in the system, rather than just the number of type
  variable bindings we attempt.
2016-08-04 20:36:47 -07:00
Doug Gregor
d0733750cc [Constraint solver] Try ‘defaultable’ bindings even if there are other possibilities.
Fixes rdar://problem/17444930.
2016-08-04 13:45:07 -07:00
Doug Gregor
87a5e4d8d8 [NFC] ConstrainSystem::getComputedBindings() is dead. Kill it. 2016-08-04 11:21:35 -07:00
Robert Widmann
f97e5dcb0e [SE-0115][1/2] Rename *LiteralConvertible protocols to ExpressibleBy*Literal. This
change includes both the necessary protocol updates and the deprecation
warnings
suitable for migration.  A future patch will remove the renamings and
make this
a hard error.
2016-07-12 15:25:24 -07:00
Joe Pamer
778a4ee136 When converting potential IUO bindings to optional
ones, look through any lvalue types. Doing so can
prevent improper double-optional binds, which can
cause unexpected runtime behavior.

(rdar://problem/26360502)
2016-06-02 11:53:27 -07:00
Chris Willmore
af0c7bd620 Initial implementation of SE-0054 "Abolish IUO Type" (#2322)
This is a squash of the following commits:

* [SE-0054] Import function pointer arg, return types, typedefs as optional

IUOs are only allowed on function decl arguments and return types, so
don't import typedefs or function pointer args or return types as IUO.

* [SE-0054] Only allow IUOs in function arg and result type.

When validating a TypeRepr, raise a diagnostic if an IUO is found
anywhere other thn the top level or as a function parameter or return
tpye.

* [SE-0054] Disable inference of IUOs by default

When considering a constraint of the form '$T1 is convertible to T!',
generate potential bindings 'T' and 'T?' for $T1, but not 'T!'. This
prevents variables without explicit type information from ending up with
IUO type. It also prevents implicit instantiation of functions and types
with IUO type arguments.

* [SE-0054] Remove the -disable-infer-iuos flag.

* Add nonnull annotations to ObjectiveCTests.h in benchmark suite.
2016-05-03 14:06:19 -07:00