Skip to content

Commit 5f8fece

Browse files
authored
Merge pull request #30757 from slavapestov/fix-function-builder-autoclosure-crash
Sema: Contextualize closures for function builder bodies also
2 parents a424ad2 + 7b4786e commit 5f8fece

File tree

4 files changed

+40
-16
lines changed

4 files changed

+40
-16
lines changed

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -812,7 +812,7 @@ Expr *DefaultArgumentExprRequest::evaluate(Evaluator &evaluator,
812812

813813
// Walk the checked initializer and contextualize any closures
814814
// we saw there.
815-
(void)TypeChecker::contextualizeInitializer(dc, initExpr);
815+
TypeChecker::contextualizeInitializer(dc, initExpr);
816816
return initExpr;
817817
}
818818

@@ -1582,7 +1582,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
15821582
if (initContext) {
15831583
// Check safety of error-handling in the declaration, too.
15841584
TypeChecker::checkInitializerErrorHandling(initContext, init);
1585-
(void)TypeChecker::contextualizeInitializer(initContext, init);
1585+
TypeChecker::contextualizeInitializer(initContext, init);
15861586
}
15871587
}
15881588
}

lib/Sema/TypeCheckStmt.cpp

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,6 @@ namespace {
8484
unsigned nextDiscriminator = 0)
8585
: ParentDC(parent), NextDiscriminator(nextDiscriminator) {}
8686

87-
bool hasAutoClosures() const {
88-
return NextDiscriminator != 0;
89-
}
90-
9187
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
9288
// Autoclosures need to be numbered and potentially reparented.
9389
// Reparenting is required with:
@@ -228,14 +224,9 @@ namespace {
228224
};
229225
} // end anonymous namespace
230226

231-
static void setAutoClosureDiscriminators(DeclContext *DC, Stmt *S) {
232-
S->walk(ContextualizeClosures(DC));
233-
}
234-
235-
bool TypeChecker::contextualizeInitializer(Initializer *DC, Expr *E) {
227+
void TypeChecker::contextualizeInitializer(Initializer *DC, Expr *E) {
236228
ContextualizeClosures CC(DC);
237229
E->walk(CC);
238-
return CC.hasAutoClosures();
239230
}
240231

241232
void TypeChecker::contextualizeTopLevelCode(TopLevelCodeDecl *TLCD) {
@@ -422,7 +413,7 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
422413
/// Type-check an entire function body.
423414
bool typeCheckBody(BraceStmt *&S) {
424415
bool HadError = typeCheckStmt(S);
425-
setAutoClosureDiscriminators(DC, S);
416+
S->walk(ContextualizeClosures(DC));
426417
return HadError;
427418
}
428419

@@ -1920,6 +1911,8 @@ TypeCheckFunctionBodyUntilRequest::evaluate(Evaluator &evaluator,
19201911

19211912
body = *optBody;
19221913
alreadyTypeChecked = true;
1914+
1915+
body->walk(ContextualizeClosures(AFD));
19231916
}
19241917
} else if (func->hasSingleExpressionBody() &&
19251918
func->getResultInterfaceType()->isVoid()) {

lib/Sema/TypeChecker.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -935,9 +935,7 @@ void checkPatternBindingCaptures(IterableDeclContext *DC);
935935

936936
/// Change the context of closures in the given initializer
937937
/// expression to the given context.
938-
///
939-
/// \returns true if any closures were found
940-
bool contextualizeInitializer(Initializer *DC, Expr *init);
938+
void contextualizeInitializer(Initializer *DC, Expr *init);
941939
void contextualizeTopLevelCode(TopLevelCodeDecl *TLCD);
942940

943941
/// Retrieve the default type for the given protocol.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// RUN: %target-swift-emit-silgen %s | %FileCheck %s
2+
3+
@_functionBuilder
4+
struct Builder {
5+
static func buildBlock<T1>(_ t1: T1) -> (T1) {
6+
return (t1)
7+
}
8+
}
9+
10+
struct Handler {
11+
var firstHandler: () -> ()
12+
var secondHandler: () -> ()
13+
}
14+
15+
// We were neglecting to assign discriminators and re-parent
16+
// autoclosures, which would manifest as curried method references
17+
// producing a bogus diagnostic about captures from inside a
18+
// nested type.
19+
class Outer {
20+
struct Inner {
21+
@Builder
22+
var build: Handler {
23+
Handler(firstHandler: self.handler, secondHandler: self.handler)
24+
}
25+
26+
private func handler() {}
27+
}
28+
}
29+
30+
// CHECK-LABEL: sil private [ossa] @$s29function_builder_curry_thunks5OuterC5InnerV5buildAA7HandlerVvgyycAEcfu_ : $@convention(thin) (Outer.Inner) -> @owned @callee_guaranteed () -> ()
31+
// CHECK-LABEL: sil private [ossa] @$s29function_builder_curry_thunks5OuterC5InnerV5buildAA7HandlerVvgyycAEcfu_yycfu0_ : $@convention(thin) (Outer.Inner) -> ()
32+
// CHECK-LABEL: sil private [ossa] @$s29function_builder_curry_thunks5OuterC5InnerV7handler33_DC254A3F89F9C7E65D25434E199F17A4LLyyF : $@convention(method) (Outer.Inner) -> ()
33+
// CHECK-LABEL: sil private [ossa] @$s29function_builder_curry_thunks5OuterC5InnerV5buildAA7HandlerVvgyycAEcfu1_ : $@convention(thin) (Outer.Inner) -> @owned @callee_guaranteed () -> ()

0 commit comments

Comments
 (0)