Move constraint generation for statement conditions onto the
constraint system; it doesn't really have any reason to be located
within the function builder transform.
Generalize the representation of contextual types so we can store
contextual types for more than one expression. Allow these to be
added/rolled back in solver scopes. Nothing uses this functionality
yet.
When requesting information about the contextual type of a constraint
system, do so using a given expression rather than treating it like
the global state that it is.
* If there is a disjunction associated with closure type e.g.
coercion to some other type `_ = { $0 } as (Int32) -> Void`
* If there is a disjunction associated with a collection which
could provide more context to the constraint solver.
If there is `subtype` relationship between two type variables
binding inference algorithm attempts to infer supertype bindings
transitively, but it doesn't check whether some of the new types
are already included in the set, which leads to duplicate solutions.
If there is a subtype relationship between N types we have to make
sure that type chain is attempted in reverse order because we can't
infer bindings transitively through type variables and attempting
it in any other way would miss potential bindings across the chain.
Instead of trying to hold a "global" set of type variable differences
let's use pair-wise comparison instead because in presence of generic
overloads such would be more precise.
If there are N solutions for a single generic overload we currently
relied on "local" comparison to detect the difference, but it's not
always possible to split the system to do one. Which means higher
level comparisons have to account for "local" (per overload choice)
differences as well otherwise ranking would loose precision.
`getCalleeLocator` has to be able to:
- Retrieve type for given expression via `getType`;
- Simplify given type via `simplifyType`; and
- Retrieve a selected overload choice for a given locator via `getOverloadFor`.
Even if contextual closure type has type variables inside
prefer it over disjunction because it provides a lot of
contextual information early which helps to solve the system
faster.
While resolving closure use contextual locator information to
determine whether given contextual type comes from a "function builder"
parameter and if so, use special `applyFunctionBuilder` to open
closure body instead of regular constraint generation.
This constraint connects type variable representing a closure
expression to its inferred type and behaves just like regular
`Defaultable` constraint expect for type inference where it's
used only if there are no contextual bindings available.
In preparation to change the way closures are handled in constraint system
let's introduce a special method which is responsible for generation of
constraints for closure body and connecting it to the rest of the
constraint system when contextual type becomes available.
In preparation to change type-checking behavior of closures
we need to introduce a special mapping from closure expressions
to their inferred types (based on parameters/result and body).
Separate closure from top-level constraint generation because
its body shouldn't be considered when it comes to parent/weight
computation, otherwise top expression in body is going to get
disconnected from the closure.
This is necessary for ambiguity diagnostics because none of the
solutions are applied back to the constraint system which means
that `getCalleeLocator` needs an ability to query information
from different sources e.g. constraint system and/or solution.
When type checking the body of a function declaration that has a function
builder on it (e.g., `@ViewBuilder var body: some View { ... }`), create a
constraint system that is responsible for constraint generation and
application, sending function declarations through the same code paths
used by closures.
Chip away at the expression-centric nature of the constraint system by
generalizing the "target" of solution application from a single
expression to a a "SolutionApplicationTarget", which can be an
expression or a function body. The latter will be used for applying
function builders to an entire function body.
Introduce a new kind of constraint, the "value witness" constraint,
which captures a reference to a witness for a specific protocol
conformance. It otherwise acts like a more restricted form of a "value
member" constraint, where the specific member is known (as a
ValueDecl*) in advance.
The constraint is effectively dependent on the protocol
conformance itself; if that conformance fails, mark the type variables
in the resolved member type as "holes", so that the conformance
failure does not cascade.
Note that the resolved overload for this constraint always refers to
the requirement, rather than the witness, so we will end up recording
witness-method references in the AST rather than concrete references,
and leave it up to the optimizers to perform devirtualization. This is
demonstrated by the SIL changes needed in tests, and is part of the
wider resilience issue with conformances described by
rdar://problem/22708391.
Previously we had a request for this in
IDETypeChecking, but this wasn't used for queries
made from Sema. Move the request into Sema, and
move `hasDynamicMemberLookupAttribute` onto
TypeBase.
There was a single place where it was used to determine whether
a binding comes from an argument conversion constraint. Since
constraint locator is part of the binding now it's possible to
use it instead and remove unused accessor.
Unify all of the fields of `PotentialBinding` which have to do with
location information into a single field with is either a constraint
(for regular bindings) or constraint locator (for "holes").
This helps to reduce the amount of space used by `PotentialBinding`
as well as propagate more contextual information when binding gets
attempted.
Rather than adjusting the opened types for choices
referring to `subscript(dynamicMember:)` down to
the result type, only use the result type to
bind the overload type variable. This avoids the
need for a couple of special cases in CSApply.
To facilitate this change, add
`ConstraintSystem::bindOverload`, which deals with
adding the necessary constraints to bind the
overload's type variable. The eventual goal here
is to remove `adjustTypeOfOverloadReference`, with
adjustments to the opened type being moved to
`getTypeOfMemberReference`, and the adding of
constraints being moved to `bindOverloadType`.
Rather than maintaining a linked list of overload
choices, which must be linearly searched each time
we need to lookup an overload at a given callee
locator, use a MapVector which can be rolled back
at the end of a scope.
Remove ResolvedOverloadSetListItem in favor of
using SelectedOverload, which avoids the need to
convert between them when moving from
ConstraintSystem to Solution.
Solutions passed to `diagnoseAmbiguityWithFixes` aren't filtered
so we need to remove all of the solutions with the score worse
than overall "best". Also logic has to account for some fixes being
"warnings".
Locator builders keep a pointer to their underlying
locator, so it's not generally sound to extend an
rvalue locator builder.
This commit enforces that withPathElement is called
on an lvalue, and adds a couple more overloads of
getConstraintLocator to make it more convenient to
extend locators with multiple elements.
Some constraint transformations require knowledge about what state
constraint system is currently in e.g. `constraint generation`,
`solving` or `diagnostics` to make a decision whether simplication
is possible. Notable example is `keypath dynamic member lookup`
which requires a presence of `applicable fn` constraint to retrieve
some contextual information.
Currently presence or absence of solver state is used to determine
whether constraint system is in `constraint generation` or `solving`
phase, but it's incorrect in case of `diagnoseFailureForExpr` which
tries to simplify leftover "active" constraints before it can attempt
type-check based diagnostics.
To make this more robust let's introduce (maybe temporarily until
type-check based diagnostics are completely obsoleted) a proper
notion of "phase" to constraint system so it is always clear what
transitions are allowed and what state constraint system is
currently in.
Resolves: rdar://problem/57201781