Skip to content

Commit 9853926

Browse files
committed
[Function builders] Make sure we contextualize closures with builders applied.
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.
1 parent a49f009 commit 9853926

File tree

4 files changed

+30
-9
lines changed

4 files changed

+30
-9
lines changed

include/swift/AST/Expr.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3599,7 +3599,10 @@ class ClosureExpr : public AbstractClosureExpr {
35993599
/// the CaptureListExpr which would normally maintain this sort of
36003600
/// information about captured variables), we need to have some way to access
36013601
/// this information directly on the ClosureExpr.
3602-
VarDecl *CapturedSelfDecl;
3602+
///
3603+
/// The bit indicates whether this closure has had a function builder
3604+
/// applied to it.
3605+
llvm::PointerIntPair<VarDecl *, 1, bool> CapturedSelfDeclAndAppliedBuilder;
36033606

36043607
/// The location of the "throws", if present.
36053608
SourceLoc ThrowsLoc;
@@ -3624,7 +3627,8 @@ class ClosureExpr : public AbstractClosureExpr {
36243627
unsigned discriminator, DeclContext *parent)
36253628
: AbstractClosureExpr(ExprKind::Closure, Type(), /*Implicit=*/false,
36263629
discriminator, parent),
3627-
BracketRange(bracketRange), CapturedSelfDecl(capturedSelfDecl),
3630+
BracketRange(bracketRange),
3631+
CapturedSelfDeclAndAppliedBuilder(capturedSelfDecl, false),
36283632
ThrowsLoc(throwsLoc), ArrowLoc(arrowLoc), InLoc(inLoc),
36293633
ExplicitResultType(explicitResultType), Body(nullptr) {
36303634
setParameterList(params);
@@ -3726,13 +3730,23 @@ class ClosureExpr : public AbstractClosureExpr {
37263730
bool hasEmptyBody() const;
37273731

37283732
/// VarDecl captured by this closure under the literal name \c self , if any.
3729-
VarDecl *getCapturedSelfDecl() const { return CapturedSelfDecl; }
3733+
VarDecl *getCapturedSelfDecl() const {
3734+
return CapturedSelfDeclAndAppliedBuilder.getPointer();
3735+
}
37303736

37313737
/// Whether this closure captures the \c self param in its body in such a
37323738
/// way that implicit \c self is enabled within its body (i.e. \c self is
37333739
/// captured non-weakly).
37343740
bool capturesSelfEnablingImplictSelf() const;
37353741

3742+
bool hasAppliedFunctionBuilder() const {
3743+
return CapturedSelfDeclAndAppliedBuilder.getInt();
3744+
}
3745+
3746+
void setAppliedFunctionBuilder(bool flag = true) {
3747+
CapturedSelfDeclAndAppliedBuilder.setInt(flag);
3748+
}
3749+
37363750
static bool classof(const Expr *E) {
37373751
return E->getKind() == ExprKind::Closure;
37383752
}

lib/Sema/CSApply.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7074,6 +7074,7 @@ namespace {
70747074
return Rewriter.coerceToType(expr, toType, locator);
70757075
});
70767076
closure->setBody(newBody, /*isSingleExpression=*/false);
7077+
closure->setAppliedFunctionBuilder();
70777078

70787079
Rewriter.solution.setExprTypes(closure);
70797080
} else if (closure->hasSingleExpressionBody()) {

lib/Sema/TypeCheckStmt.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,10 @@ namespace {
144144
}
145145
}
146146

147-
// If the closure has a single expression body, we need to walk into it
148-
// with a new sequence. Otherwise, it'll have been separately
149-
// type-checked.
150-
if (CE->hasSingleExpressionBody())
147+
// If the closure has a single expression body or has had a function
148+
// builder applied to it, we need to walk into it with a new sequence.
149+
// Otherwise, it'll have been separately type-checked.
150+
if (CE->hasSingleExpressionBody() || CE->hasAppliedFunctionBuilder())
151151
CE->getBody()->walk(ContextualizeClosures(CE));
152152

153153
TypeChecker::computeCaptures(CE);

test/Constraints/function_builder.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -352,14 +352,20 @@ func acceptComponentBuilder(@ComponentBuilder _ body: () -> Component) {
352352
print(body())
353353
}
354354

355+
func colorWithAutoClosure(_ color: @autoclosure () -> Color) -> Color {
356+
return color()
357+
}
358+
359+
var trueValue = true
355360
acceptComponentBuilder {
356361
"hello"
357-
if true {
362+
if trueValue {
358363
3.14159
364+
colorWithAutoClosure(.red)
359365
}
360366
.red
361367
}
362-
// CHECK: array([main.Component.string("hello"), main.Component.optional(Optional(main.Component.array([main.Component.floating(3.14159)]))), main.Component.color(main.Color.red)])
368+
// CHECK: array([main.Component.string("hello"), main.Component.optional(Optional(main.Component.array([main.Component.floating(3.14159), main.Component.color(main.Color.red)]))), main.Component.color(main.Color.red)])
363369

364370
// rdar://53325810
365371

0 commit comments

Comments
 (0)