When applying a function builder to a closure to produce the final,
type-checked closure, use the new rewriteTarget() so it’s performed on
a per-target basis. Use this to eliminate some duplicating in the handling
of return types.
Pull out the core operation of rewriting a given SolutionApplicationTarget
into into a method on the ExprWalker that does the overall rewrite, so it
can be called multiple times within application.
Rather than having separate dense maps for the type mappings of each
node type (expression, type location, variable declaration, pattern) that
a TypedNode can be, have a single such map. Sometimes we end up
setting a particular node's type more than once, so cope with that
by restoring the prior type.
Move the remaining logic of typeCheckBinding, which consists of applying
the solution to the pattern, down into the normal solution application
path. typeCheckBinding() is now a thin shell over the normal
typeCheckExpression() convenience function.
Sink the solution-application code from typeCheckBinding’s
ExprTypeCheckListener subclass into normal solution application, allowing
us to eliminate this subclass entirely. Down to one…
Sink the constraint generation for initialization patterns, including all
of the logic for property wrappers, from the high-level entry point
`typeCheckBinding` down into the lower-level constraint generation for
solution application targets.
Capture the peculiarities of contextual types vs. types used to generate
conversion constraints, as well as the behavior of “optional some” patterns
as used by if let / while let, within SolutionApplicationTarget. This allows
us to use a single target throughout setup / solving / application, rather
than mapping between two similar-but-disjoint targets.
Rework most of typeCheckExpression() to use SolutionApplicationTarget,
folding more information into that data structure and sinking more
expression-checking behavior down into the more general solver and
solution-application code.
For code like
```
_ = type(of: x).A.self
```
the `A` type reference is written explicitely by the user, but the AST created using `TypeExpr::createImplicitHack` is hiding such a reference,
making the reference invisible to semantic functionality like 'rename'.
rdar://56885871
Start cleaning up the main “solve” entry point for solving an expression
and applying the solution, so it handles arbitrary solution targets.
This is another small step that doesn’t do much on its own, but will help
with unifying the various places in the code base where we run the solver.
Add the final conversion type and the flag indicating whether a given
expression is discarded to SolutionApplicationTarget, rather than
separating the arguments to the solver implementation.
SolutionResult better captures what can happen when solving a constraint
system for the given expression occurs than the ad hoc SolutionKind return
& small vector of Solution results. Also, try to make this logic less
convoluted.
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.
We used to get this contextualization "for free" because closures that
had function builders applied to them would get translated into
single-expression closures. Now, we need to check for this explicitly.
`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`.
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 `ImplicitCallAsFunction` locator path
element to represent an implicit member reference
to `callAsFunction`. Then adjust CSApply a little
to check whether it's finishing an apply for a
callable type, and if so build the implicit member
access.
Have callers resolve the SelectedOverload instead of the callee. Then make the error paths more apparent, and flush Optional<SelectedOverload> wherever it can be found.
Constraint application was rewriting conditional casts (as?) and
forced casts (as!) into coercions (as) at the AST level when it
determined that there was a coercion. Stop doing that: it's the
optimizer's job to remove such casts.
Rather than spinning up a new constraint system when performing an "as"
coercion, perform the coercion with the known solution, because we
already did all of the work to figure out how to perform the coercion.
In this case we would "devirtualize" the protocol requirement call
by building the AST to model a direct reference to the witness.
Previously this was done by recursively calling typeCheckExpression(),
but the only thing this did was recover the correct substitutions
for the call.
Instead, we can just build the right SubstitutionMap directly.
Unfortunately, while we serialize enough information in the AST
to devirtualize calls at the SIL level, we do not for AST Exprs.
This is because SIL devirtualization builds a reference to the
witness thunk signature, which is an intermediate step between
the protocol requirement and the witness. I get around this by
deriving the substitutions from walking in parallel over the
interface type of the witness, together with the inferred type
of the call expression.