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.
Reimplement the witness matching logic used for generic requirements
so that it properly models the expectations required of the witness,
then captures the results in the AST. The new approach has a number of
advantages over the existing hacks:
* The constraint solver no longer requires hacks to try to tangle
together the innermost archetypes from the requirement with the
outer archetypes of the context of the protocol
conformance. Instead, we create a synthetic set of archetypes that
describes the requirement as it should be matched against
witnesses. This eliminates the infamous 'SelfTypeVar' hack.
* The type checker no longer records substitutions involving a weird
mix of archetypes from different contexts (see above), so it's
actually plausible to reason about the substitutions of a witness. A
new `Witness` class contains the declaration, substitutions, and all
other information required to interpret the witness.
* SILGen now uses the substitution information for witnesses when
building witness thunks, rather than computing all of it from
scratch. ``substSelfTypeIntoProtocolRequirementType()` is now gone
(absorbed into the type checker, and improved from there), and the
witness-thunk emission code is simpler. A few other bits of SILGen
got simpler because the substitutions can now be trusted.
* Witness matching and thunk generation involving generic requirements
and nested generics now works, based on some work @slavapestov was
already doing in this area.
* The AST verifier can now verify the archetypes that occur in witness substitutions.
* Although it's not in this commit, the `Witness` structure is
suitable for complete (de-)serialization, unlike the weird mix of
archetypes previously present.
Fixes rdar://problem/24079818 and cleans up an area that's been messy
and poorly understood for a very, very long time.
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.
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.
ConstraintSystem::addConstraint() is no longer used to simplify
existing constraints, nor does it have to deal with "externally
solved" constraints. Remove those parameters and simplify the code. NFC
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
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).
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.
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.
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.
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.
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.
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.
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.
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.
Extend the handling of function reference kinds to member references
(e.g., x.f), and therefore the logic for stripping argument labels. We
appear to be stripping argument labels from all of the places where it
is required.
When referencing a function in the type checker, drop argument labels
when we don't need them to type-check an immediate call to that
function. This provides the semantic behavior of SE-0111, e.g.,
references to functions as values produce unlabeled function types,
without the representational change of actually dropping argument
labels from the type system.
At the moment, this only works for bare references to functions. It
still needs to be pushed through more of the type checker and more AST
nodes to work in the general case.
Keep this work behind the frontend flag
-suppress-argument-labels-in-types for now.