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.
ASTScopes completely skip implicit pattern bindings, so don't mark
generated ones as implicit. Instead, give them suitable source
location information.
Fixes rdar://problem/58710568.
The right solution is to extend the notion of the "anchor" of a locator
to also cover statements (and TypeReprs, and Patterns, and more), so
this is a stop-gap.
A couple of trivial fixes as part of the builder transform refactoring:
* When recording captured expressions, record the source entity appropriately
* Make sure to check (and skip) #if declarations in application
* Check and diagnostic #warning/#error as part of application (not generation)
* Simplify the body result type for return coercion during application
* When checking for applicability of a function builder, don't do any
constraint generation.
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.
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.
If a function builder type has a static method buildExpression(), use
it to pass through each expression whose value will become part of the
final result. This is part of the function builders pitch that had not
yet been implemented.
When we transform each expression or statement in a function builder,
introduce a one-way constraint so that type information does not flow
backwards from the context into that statement or expression. This
more closely mimics the behavior of normal code, where type inference
is per-statement, flowing from top to bottom.
This also allows us to isolate different expressions and statements
within a closure that's passed into a function builder parameter,
reducing the search space and (hopefully) improving compile times for
large function builder closures.
For now, put this functionality behind the compiler flag
`-enable-function-builder-one-way-constraints` for testing purposes;
we still have both optimization and correctness work to do to turn
this on by default.
Prior to this patch, we pre-checked the result of applying the function-builder transformation, but only when we hadn't already pre-checked the closure before. This causes two problems to arise when the transformation is applied to the same closure along multiple branches of a disjunction. The first is that any expressions that are synthesized by the transformation will not be pre-checked the second time through, which is a problem if we try to apply different builder types to the same closure (we do cache expressions for identical builder types). The second is that the pre-check will rewrite sub-expressions in place *in the synthesized expression*, which means that top-level expressions in the original closure body (including `if` conditions) that are now nested in the synthesized expression will not be rewritten in the original closure and therefore will be encountered in their raw state the second time through.
This patch causes all expressions in the original closure body to be pre-checked before doing any other work. We then pre-check the synthesized expression immediately before generating constraints for it in order to set up the AST appropriately for CSGen; this could be skipped if we just synthesized expressions the way that CSGen wants them, but that seems to be somewhat involved.
Pre-checking is safe to apply to an expression multiple times, so it's
fine if we take this path and then decide not to use a function builder.
I've also merged the check for `return` statements into this same walk, which was convenient.
Fixes rdar://53325810 at least, and probably also some bugs with applying different function builders to the same closure.
Instead of being a completely separate body type-checking pass, refactor
this function so it does the function builder transform on the body, then
continues with the rest of typeCheckFunctionBodyUntil() as normal.
When performing code-completion inside the body of a @functionBuilder
closure/function, set the flag to suppress diagnostics. This works
around a big performance problem in some complex bodies that do not
typecheck, which is typical during code-completion. A real-world example
with SwitfUI went from ~50 seconds to 0.5. We do not disable diagnostics
in general because the diagnostic paths provide falback types that are
useful to code-completion.
rdar://52356229
Dropping the IfConfigDecl is not a great implementation, but it'll work
well enough to unblock this code while we work to allow multi-statement
bodies in general.