Make SolverState manage whether the ConstraintSystem it belongs to has a
current SolverState.
Also a couple minor formatting fixes for ternary expressions involving
solverState.
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.
When we process a constraint, the first step is generally to call
getFixedTypeRecursive() to look through type variables. When this
operation actually does non-trivial work, we could save
that result by considering the current constraint "solved" and
generating a new constraint (if needed!) with the simplified types.
This commit adds the infrastructure to do that, because it's important
when getFixedTypeRecursive() starts performing more interesting
substitutions (e.g., handling member types of type
variables). However, enabling for the common case of looking through a
type variable isn't profitable (it's ~2% slower to type-check the
standard library). Stage in this infrastructure change now.
When performing the occurs check, look for the *representative* of the
type variable we're about to bind, rather than the type variable
itself. Fixes rdar://problem/26845038, SR-1512, SR-1902, SR2635,
SR-2852, and SR-2766.
We've been performing the "occurs" check when computing potential
bindings for type variables, but we weren't actually performing the
check for bindings that *must* occur. Perform the occurs check before
binding type variables, which fixes a few crashers and is far more principled.
Note that this obviates the need for tracking the type variables we've
substituted in simplifyType(), so simplify that as well.
Fixes rdar://problem/27879334 / SR-2351.
Our existential metatype conversion/conformance handling in the type
checker was tripped up the refactoring to lazily introduce
constraints, because it dependended on the otherwise-unused
TypeMatchKind::ConformsTo. Eliminate TypeMatchKind::ConformsTo and
simplify the code here.
Start migrating the main ConstraintSolver::addConstraint() entrypoint
for relational constraints over to the model where it simplifies
first, then only creates a new constraint if the constraint it built
cannot be solved. This covers only the main relational
constraints--there are a number of other relational constraint kinds
to handle this way.
When adding a new member constraint, try to immediately simplify it,
generating a constraint when it cannot be resolved. Note that we also
generate constraints in top-level failure cases, so that the
diagnostics machinery can find it after-the-fact.
When adding a 'restricted' constraint, go straight into the 'simplify'
operation. A new constraint will only be allocated and recorded if it
cannot be immediately simplified. To get here, be more rigorous about passing TMF_GenerateConstraints through simplifyRestrictedConstraint().
When we're creating a new constraint because we couldn't solve it (and
need to record the result), do so without trying to simplify it yet
again. It's just wasted work.
When adding constraints into the constraint system, don't immediately
allocate a Constraint and add it via the most-general
addConstraint(). Instead, go through a more specific entrypoint (e.g.,
addValueMemberConstraint, addRestrictedConstraint, etc.), so we can
start phasing out the general "add an already-formed constraint"
function. NFC
Always check arguments of the tuple type against corresponding parameters,
otherwise for a single argument functions e.g. foo(_ a: Any) after SE-0046
type checker is going to produce incorrect solution.
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)
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.
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).
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.
This fixes a usability regression with the removal of @noreturn
in Swift 3. Previously, it was legal to write this:
let callback: () -> Int = { fatalError() }
Now that the special @noreturn attribute has been replaced with
a Never type, the above fails to typecheck, because the expression
now has type 'Never', and we expect a value of type 'Int'.
Getting around this behavior requires ugly workarounds to force the
parser to treat the body as a statement rather than an expression;
for example,
let callback: () -> Int = { _ = (); fatalError() }
This patch generalized single-expression closures to allow
the 'Never to T' conversion. Note that this is rather narrow
in scope -- it only applies to closure *literals*, single-expression
ones at that, not arbitrary function *values*.
In fact, it is not really a conversion at all, but more of a
desugaring rule for single-expression closures. They can now be
summarized as follows:
- If the closure literal has contextual return type T and
the expression has Never type, the closure desugars as
{ _ = <expr> }, with no ReturnStmt.
- If the closure literal has contextual return type T for some
non-void type T, the closure desugars as { return <expr> };
the expression type must be convertible to T.
- If the closure literal has contextual return type Void, and
the expression has some non-Void type T, the closure
desugars as { _ = <expr>; return () }.
Fixes <rdar://problem/28269358> and <https://bugs.swift.org/browse/SR-2661>.
Long term, we want to refactor the AST to reflect the current
programming model in Swift. This would include refactoring
FunctionType to take a list of ParameterTypeElt, or something with a
better name, that can contain both the type and flags/bits that are
only specific to types in parameter position, such as @autoclosure and
@escaping. At the same time, noescape-by-default has severely hurt our
ability to print types without significant context, as we either have
to choose to too aggressively print @escaping or not print it in every
situation it occurs, or both.
As a gentle step towards the final solution, without uprooting our
overall AST structure, and as a way towards fixing the @escaping
printing ails, put these bits on the TupleTypeElt and ParenType, which
will serve as a model for what ParameterTypeElt will be like in the
future. Re-use these flags on CallArgParam, to leverage shared
knowledge in the type system. It is a little painful to tack onto
these types, but it's minor and will be overhauled soon, which will
eventually result in size savings and less complexity overall.
This includes all the constraint system adjustments to make these
types work and influence type equality and overload resolution as
desired. They are encoded in the module format. Additional tests
added.
The type checker had some logic for performing specific checking for
explicit bridging casts of generic types based on knowledge of
Array/Dictionary/Set, but pretended no other bridged generic types
existed. That's incorrect now; simply require them to match exactly.
Fixes rdar://problem/27539951.
This eliminates a pile of now-dead code in:
* The type checker, where we no longer have special cases for bridging conversions
* The expression ASTs, where we no longer need to distinguish bridging collection up/down casts
* SILGen, which no longer uses
Still to come is the removal of the
_(set|dictionary)Bridge(From|To)ObjectiveC(Conditional)? entrypoints
from the standard library. They're still used by some tests.
Simplify e.g., ASTContext::getBridgedToObjC(), which no longer needs
the optional return.
Eliminate the now-unused constraint kind for checking bridging to
Objective-C.
Suppose you have this protocol:
protocol P {
typealias A = Int
typealias B = Self
}
Clearly, 'P.B' does not make sense, because then the type parameter
would "leak out" of the existential container. However, 'P.A' is totally
fine, it just means 'Int'.
Previously, we would allow 'P.A' in type context, and diagnose on 'P.B'.
However, due to an oversight, neither one was allowed in expression
context, so for example you could not write 'P.A.self', even though
that should just mean 'Int.self'.
Fix this by generalizing performMemberLookup(), and fix up some
diagnostics to be more specific when something is wrong -- we want
to avoid talking about typealiases as 'static members', since that
doesn't really make much sense.
Fixes <https://bugs.swift.org/browse/SR-2314>.
Previously, qualified lookup would use a metatype to signal
to the LookupResultBuilder that conformance checks should not
be used to resolve protocol members found with a concrete
type base. This is too subtle for my taste. Add an explicit
flag and clean up some usages, fixing <rdar://problem/16123805>.
Also, clean up the 'CheckProtocolMembers' flag. We now set
when the base type is an archetype, and correctly handle
the concept of an abstract conformance. This finally
fixes <rdar://problem/22776964>.
For associated types inferred to be Any, we were allowing the type to
satisfy more specific same-type constraints, e.g. Element ==
Character (where Element is the associated type). This is clearly wrong.
The fix here is very specific to empty protocol compositions, and
removes some code in matchTypes() that doesn't make a lot of
sense. Looking back at the history, this was added in a commit that made
a handful of other changes, and it's not clear this particular change
was important for the issues that commit claimed to fix (and in fact
removing this regresses no tests).
Fixes rdar://problem/27515965.