Implement support for switch statements within function builders. Cases can
perform arbitrary pattern matches, e.g.,
tuplify(true) { c in
"testSwitchCombined"
switch e {
case .a:
"a"
case .b(let i, _?), .b(let i, nil):
i + 17
}
}
subject to the normal rules of switch statements. Cases within function
builders cannot, however, include “fallthrough” statements, because those
(like “break” and “continue”) are control flow.
The translation of performed for `switch` statements is similar to that of
`if` statements, using `buildEither(first:)` and `buildEither(second:)` on
the function builder type.
This is the bulk of switch support, tracked by rdar://problem/50426203.
Teach pattern matching involving "as" patterns to work properly in
function builders. The code almost handled this, but prematurely
prechecking expressions in patterns broke it.
Use the generalized constraint generation and binding for patterns to
introduce support for if-let and if-case in function builders, handling
arbitrary patterns.
Part of function builder generalization, rdar://problem/50426203.
Introduce support for initialized let/var declarations within function
builder closures, e.g.,
let (a, b) = c()
We generate constraints for the declarations as elsewhere, but the types of
the declared variables (a and b in this case) are bound to the type of the
pattern by one-way constraints, to describe the flow of type information
through the closure.
Implements rdar://problem/57330696.
Collect all references to parameters whose types involve type variables,
including in closures that aren’t single-expression. This fixes a type
checker assertion that occurs when the constraint graph can get disconnected
with the combination of delayed constraint generation for single-expression
closures and the use of function builders.
Fixes rdar://problem/58695803.
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.
Attempt to infer a closure type based on its parameters and body
and put it aside until contextual type becomes available or it
has been determined that there is no context.
Once all appropriate conditions are met, generate constraints for
the body of the closure and bind it the previously inferred type.
Doing so makes it possible to pass single-statement closures as
an argument to a function builder parameter.
Resolves: SR-11628
Resolves: rdar://problem/56340587
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.
Now that we associate argument labels for key path
subscript components, remove the special logic for
it. In addition, we can now search for callees
directly by using `getCalleeLocator`, as it should
now be able to find all the correct callees that
`getCalleeDeclAndArgs` does.
By using `getCalleeLocator`, we now also correctly
resolve callees for operator calls, meaning that
we can now use them with function builders. In
addition, we no longer incorrectly resolve callees
for calls made on SubscriptExprs.
Resolves SR-11439 & SR-11440.
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.
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.
A substantial amount of this patch goes towards trying to get at least
minimal diagnostics working, since of course I messed up the rule a few
times when implementing this.
rdar://50149837
Since we short-circuit in the function builder application when we
hit something we cannot translate, relying on that visitor to
detect 'return' statements (which disable the application) is bogus.
Use a separate, earlier visitor to find 'return' statements consistently.
Fixes rdar://problem/50266341.
Use the opened type from the callee declaration to open up references to
generic function builders that contain type parameters. This allows general
use of generic function builders.
If a function builder contains a buildIf function, then "if" statements
will be supported by passing an optional of the "then" branch.
"if" statements with an "else" statement are unsupported at present.
When calling a function whose parameter specifies a function builder
with a multi-statement closure argument, transform the closure into
a single expression via the function builder. Should the result
type checker, replace the closure body with the single expression.