This parameter implements getType() for the given expression, making
it possible to use this from within the constraint system, which now
has it's own side map for types of expressions.
Switch ConstraintSystem::getType() to returning the type from the
constraint system type map.
For now, assert that these types equal the types in the expression
nodes since we are still setting the expression node types in
ConstraintSystem::setType().
Instead of relying on the SolverScope to rollback all of the changes
done to constraints in the system at the end of its life time, move
all of the logic handling that into SolverState where retired/generated
constraints live.
Since retired constraints are re-added back to the circulation in LIFO
order, make sure that all of the constraints are added to the front of
SolverScope::retiredConstraints list.
Update CSGen/CSApply/CSSolver to primarily use getType() from
ConstraintSystem.
Currently getType() just returns the type on the expression. As with
setType(), which continues to set the type on the expression, this
will be updated once all the other changes are in place.
This change also moves coerceToRValue from TypeChecker to
CosntraintSystem so that it can access the expression type map in the
constraint system.
I've been unable to reproduce the issue that hit on the builder, and
still expect this change to be NFC, so trying it out again. If it
fails, I'll revert again and try another shot at reproducing.
Original commit message:
We create new expressions that have the type on the expression
set. Make sure we capture these types in the constraint system type
map so that we can refer to types uniformally by consulting the map.
NFC.
(cherry picked from commit 57d5d974ff)
We create new expressions that have the type on the expression
set. Make sure we capture these types in the constraint system type
map so that we can refer to types uniformally by consulting the map.
NFC.
The setType() function in ConstraintSystem still sets the types on the
expressions themselves and that will continue until everything is
moved over to using the map.
Unfortunately this exposed cases where we are currently setting the
type multiple times to different values, so I've commented out the
assert that I previously added. I will circle back and start looking
into those issues once everything is moved over.
NFC for now.
This map will be used instead of directly accessing types on
expressions. This will allow us to avoid mutating the types on
expression trees directly, making it possible to remove code that
currently attempts to save & restore types, and reducing the number of
bugs that exist as a result of not always perfectly saving & restoring
types (e.g. dangling references to released type variables).
The setType() function introduced here currently still sets the type
on the expression, so this change is NFC. This is just step one of
staging in this transition to using the types from the maps.
A map for TypeLocs and possibly other maps for other types we mutate
will be added in future commits.
This makes sure that removed constraints are returned back to the
system after current run, otherwise only constraint graph would
get them back since it has its own scope.
Make SolverState manage whether the ConstraintSystem it belongs to has a
current SolverState.
Also a couple minor formatting fixes for ternary expressions involving
solverState.
The ASTContext had a wacky "get member type" callback that actually
called back into the constraint system (!) to build member types. This
callback was obsoleted by the change that started representing nested
types as DependentMemberTypes.
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.
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.
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().