Construct AutoClosureExpr With Deeper Parent Contexts

AutoClosureExprs created by the constraint system used to be constructed
with the decl context of the constraint system itself. This meant that
autoclosures in expressions nested in closures would initially be
parented onto any enclosing functions rather than the deepest closure
context. When we ran capture analysis and lookup from inside of the body
of these nascent values, we would fail to find declarations brought into
scope by those parent closures. This is especially relevant when
pre-typechecked code is involved since captures for those declarations
will be forced before their bodies have been recontextualized. See
issue #34230 for why we need to force things so early.

The attached test case demonstrates both bugs: The former a bogus lookup
through the parent context that would incorrectly reject this otherwise
well-formed code. The latter is a crash in SILGen when the capture
computation would fail to note $0.

Use the decl context of the solution application target, which is always
going to be the deepest user-written closure expression available to us,
and therefore the deepest scope that can introduce capturable variables.

rdar://79248469
This commit is contained in:
Robert Widmann
2021-07-02 16:57:10 -07:00
parent 1ca4d7cbc3
commit c64427fb6c
4 changed files with 60 additions and 13 deletions

View File

@@ -5098,6 +5098,7 @@ ConstraintSystem::isConversionEphemeral(ConversionRestrictionKind conversion,
Expr *ConstraintSystem::buildAutoClosureExpr(Expr *expr,
FunctionType *closureType,
DeclContext *ClosureContext,
bool isDefaultWrappedValue,
bool isAsyncLetWrapper) {
auto &Context = DC->getASTContext();
@@ -5116,8 +5117,9 @@ Expr *ConstraintSystem::buildAutoClosureExpr(Expr *expr,
newClosureType = closureType->withExtInfo(info.withNoEscape(false))
->castTo<FunctionType>();
auto *closure = new (Context) AutoClosureExpr(
expr, newClosureType, AutoClosureExpr::InvalidDiscriminator, DC);
auto *closure = new (Context)
AutoClosureExpr(expr, newClosureType,
AutoClosureExpr::InvalidDiscriminator, ClosureContext);
closure->setParameterList(ParameterList::createEmpty(Context));