Skip to content

Commit d7f4b1a

Browse files
committed
AST: Capture list bindings now point back to their parent CaptureListExpr
We'll need this to get the right 'selfDC' when name lookup finds a 'self' declaration in a capture list, eg class C { func bar() {} func foo() { _ = { [self] in bar() } } }
1 parent 8e6346e commit d7f4b1a

25 files changed

+79
-81
lines changed

include/swift/AST/Decl.h

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ namespace swift {
6262
class DynamicSelfType;
6363
class Type;
6464
class Expr;
65+
class CaptureListExpr;
6566
class DeclRefExpr;
6667
class ForeignAsyncConvention;
6768
class ForeignErrorConvention;
@@ -352,13 +353,10 @@ class alignas(1 << DeclAlignInBits) Decl {
352353
IsStatic : 1
353354
);
354355

355-
SWIFT_INLINE_BITFIELD(VarDecl, AbstractStorageDecl, 1+1+1+1+1+1+1+1,
356+
SWIFT_INLINE_BITFIELD(VarDecl, AbstractStorageDecl, 1+1+1+1+1+1+1,
356357
/// Encodes whether this is a 'let' binding.
357358
Introducer : 1,
358359

359-
/// Whether this declaration was an element of a capture list.
360-
IsCaptureList : 1,
361-
362360
/// Whether this declaration captures the 'self' param under the same name.
363361
IsSelfParamCapture : 1,
364362

@@ -4892,16 +4890,19 @@ class VarDecl : public AbstractStorageDecl {
48924890
};
48934891

48944892
protected:
4895-
PointerUnion<PatternBindingDecl *, Stmt *, VarDecl *> Parent;
4893+
PointerUnion<PatternBindingDecl *,
4894+
Stmt *,
4895+
VarDecl *,
4896+
CaptureListExpr *> Parent;
48964897

48974898
VarDecl(DeclKind kind, bool isStatic, Introducer introducer,
4898-
bool isCaptureList, SourceLoc nameLoc, Identifier name,
4899-
DeclContext *dc, StorageIsMutable_t supportsMutation);
4899+
SourceLoc nameLoc, Identifier name, DeclContext *dc,
4900+
StorageIsMutable_t supportsMutation);
49004901

49014902
public:
4902-
VarDecl(bool isStatic, Introducer introducer, bool isCaptureList,
4903+
VarDecl(bool isStatic, Introducer introducer,
49034904
SourceLoc nameLoc, Identifier name, DeclContext *dc)
4904-
: VarDecl(DeclKind::Var, isStatic, introducer, isCaptureList, nameLoc,
4905+
: VarDecl(DeclKind::Var, isStatic, introducer, nameLoc,
49054906
name, dc, StorageIsMutable_t(introducer == Introducer::Var)) {}
49064907

49074908
SourceRange getSourceRange() const;
@@ -5091,8 +5092,22 @@ class VarDecl : public AbstractStorageDecl {
50915092
Bits.VarDecl.Introducer = uint8_t(value);
50925093
}
50935094

5095+
CaptureListExpr *getParentCaptureList() const {
5096+
if (!Parent)
5097+
return nullptr;
5098+
return Parent.dyn_cast<CaptureListExpr *>();
5099+
}
5100+
5101+
/// Set \p v to be the pattern produced VarDecl that is the parent of this
5102+
/// var decl.
5103+
void setParentCaptureList(CaptureListExpr *expr) {
5104+
assert(expr != nullptr);
5105+
Parent = expr;
5106+
}
50945107
/// Is this an element in a capture list?
5095-
bool isCaptureList() const { return Bits.VarDecl.IsCaptureList; }
5108+
bool isCaptureList() const {
5109+
return getParentCaptureList() != nullptr;
5110+
}
50965111

50975112
/// Is this a capture of the self param?
50985113
bool isSelfParamCapture() const { return Bits.VarDecl.IsSelfParamCapture; }

include/swift/AST/TypeAlignments.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ namespace swift {
3232
class ASTContext;
3333
class AttributeBase;
3434
class BraceStmt;
35+
class CaptureListExpr;
3536
class Decl;
3637
class DeclContext;
3738
class Expr;
@@ -112,6 +113,7 @@ LLVM_DECLARE_TYPE_ALIGNMENT(swift::BraceStmt, swift::StmtAlignInBits)
112113
LLVM_DECLARE_TYPE_ALIGNMENT(swift::ASTContext, 2);
113114
LLVM_DECLARE_TYPE_ALIGNMENT(swift::DeclContext, swift::DeclContextAlignInBits)
114115
LLVM_DECLARE_TYPE_ALIGNMENT(swift::Expr, swift::ExprAlignInBits)
116+
LLVM_DECLARE_TYPE_ALIGNMENT(swift::CaptureListExpr, swift::ExprAlignInBits)
115117
LLVM_DECLARE_TYPE_ALIGNMENT(swift::AbstractClosureExpr, swift::ExprAlignInBits)
116118
LLVM_DECLARE_TYPE_ALIGNMENT(swift::OpaqueValueExpr, swift::ExprAlignInBits)
117119
LLVM_DECLARE_TYPE_ALIGNMENT(swift::ProtocolConformance, swift::DeclAlignInBits)

lib/AST/Decl.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1667,7 +1667,8 @@ void PatternBindingDecl::setPattern(unsigned i, Pattern *P,
16671667
// PatternBindingDecl as their parent.
16681668
if (P)
16691669
P->forEachVariable([&](VarDecl *VD) {
1670-
VD->setParentPatternBinding(this);
1670+
if (!VD->isCaptureList())
1671+
VD->setParentPatternBinding(this);
16711672
});
16721673
}
16731674

@@ -5399,12 +5400,11 @@ Type AbstractStorageDecl::getValueInterfaceType() const {
53995400
}
54005401

54015402
VarDecl::VarDecl(DeclKind kind, bool isStatic, VarDecl::Introducer introducer,
5402-
bool isCaptureList, SourceLoc nameLoc, Identifier name,
5403+
SourceLoc nameLoc, Identifier name,
54035404
DeclContext *dc, StorageIsMutable_t supportsMutation)
54045405
: AbstractStorageDecl(kind, isStatic, dc, name, nameLoc, supportsMutation)
54055406
{
54065407
Bits.VarDecl.Introducer = unsigned(introducer);
5407-
Bits.VarDecl.IsCaptureList = isCaptureList;
54085408
Bits.VarDecl.IsSelfParamCapture = false;
54095409
Bits.VarDecl.IsDebuggerVar = false;
54105410
Bits.VarDecl.IsLazyStorageProperty = false;
@@ -5444,6 +5444,10 @@ bool VarDecl::isSettable(const DeclContext *UseDC,
54445444
// initialized.
54455445
if (hasNonPatternBindingInit())
54465446
return false;
5447+
5448+
// Capture list bindings are never settable.
5449+
if (isCaptureList())
5450+
return false;
54475451

54485452
// Properties in structs/classes are only ever mutable in their designated
54495453
// initializer(s).
@@ -6095,8 +6099,7 @@ ParamDecl::ParamDecl(SourceLoc specifierLoc,
60956099
DeclContext *dc)
60966100
: VarDecl(DeclKind::Param,
60976101
/*IsStatic*/ false,
6098-
VarDecl::Introducer::Let,
6099-
/*IsCaptureList*/ false, parameterNameLoc, parameterName, dc,
6102+
VarDecl::Introducer::Let, parameterNameLoc, parameterName, dc,
61006103
StorageIsNotMutable),
61016104
ArgumentNameAndDestructured(argumentName, false),
61026105
ParameterNameLoc(parameterNameLoc),

lib/AST/Expr.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1243,7 +1243,12 @@ CaptureListExpr *CaptureListExpr::create(ASTContext &ctx,
12431243
ClosureExpr *closureBody) {
12441244
auto size = totalSizeToAlloc<CaptureListEntry>(captureList.size());
12451245
auto mem = ctx.Allocate(size, alignof(CaptureListExpr));
1246-
return ::new(mem) CaptureListExpr(captureList, closureBody);
1246+
auto *expr = ::new(mem) CaptureListExpr(captureList, closureBody);
1247+
1248+
for (auto capture : captureList)
1249+
capture.Var->setParentCaptureList(expr);
1250+
1251+
return expr;
12471252
}
12481253

12491254
DestructureTupleExpr *

lib/ClangImporter/ImportDecl.cpp

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,6 @@ createVarWithPattern(ASTContext &ctx, DeclContext *dc, Identifier name, Type ty,
138138
// Create a variable to store the underlying value.
139139
auto var = new (ctx) VarDecl(
140140
/*IsStatic*/false, introducer,
141-
/*IsCaptureList*/false,
142141
SourceLoc(), name, dc);
143142
if (isImplicit)
144143
var->setImplicit();
@@ -1621,7 +1620,7 @@ static void makeStructRawValuedWithBridge(
16211620

16221621
// Create a computed value variable.
16231622
auto computedVar = new (ctx) VarDecl(
1624-
/*IsStatic*/false, VarDecl::Introducer::Var, /*IsCaptureList*/false,
1623+
/*IsStatic*/false, VarDecl::Introducer::Var,
16251624
SourceLoc(), computedVarName, structDecl);
16261625
computedVar->setInterfaceType(bridgedType);
16271626
computedVar->setImplicit();
@@ -1902,7 +1901,7 @@ static bool addErrorDomain(NominalTypeDecl *swiftDecl,
19021901

19031902
// Make the property decl
19041903
auto errorDomainPropertyDecl = new (C) VarDecl(
1905-
/*IsStatic*/isStatic, VarDecl::Introducer::Var, /*IsCaptureList*/false,
1904+
/*IsStatic*/isStatic, VarDecl::Introducer::Var,
19061905
SourceLoc(), C.Id_errorDomain, swiftDecl);
19071906
errorDomainPropertyDecl->setInterfaceType(stringTy);
19081907
errorDomainPropertyDecl->setAccess(AccessLevel::Public);
@@ -2901,7 +2900,6 @@ namespace {
29012900
auto nsErrorType = nsErrorDecl->getDeclaredInterfaceType();
29022901
auto nsErrorProp = new (C) VarDecl(/*IsStatic*/false,
29032902
VarDecl::Introducer::Let,
2904-
/*IsCaptureList*/false,
29052903
loc, C.Id_nsError,
29062904
errorWrapper);
29072905
nsErrorProp->setImplicit();
@@ -2977,7 +2975,6 @@ namespace {
29772975
auto varName = C.Id_rawValue;
29782976
auto rawValue = new (C) VarDecl(/*IsStatic*/false,
29792977
VarDecl::Introducer::Var,
2980-
/*IsCaptureList*/false,
29812978
SourceLoc(), varName,
29822979
enumDecl);
29832980
rawValue->setImplicit();
@@ -3664,7 +3661,6 @@ namespace {
36643661
AccessLevel::Public,
36653662
/*IsStatic*/false,
36663663
VarDecl::Introducer::Var,
3667-
/*IsCaptureList*/false,
36683664
Impl.importSourceLoc(decl->getBeginLoc()),
36693665
name, dc);
36703666
result->setInterfaceType(type);
@@ -3970,7 +3966,6 @@ namespace {
39703966
Impl.createDeclWithClangNode<VarDecl>(decl, AccessLevel::Public,
39713967
/*IsStatic*/ false,
39723968
VarDecl::Introducer::Var,
3973-
/*IsCaptureList*/false,
39743969
Impl.importSourceLoc(decl->getLocation()),
39753970
name, dc);
39763971
if (decl->getType().isConstQualified()) {
@@ -4058,7 +4053,6 @@ namespace {
40584053
auto result = Impl.createDeclWithClangNode<VarDecl>(decl,
40594054
AccessLevel::Public,
40604055
/*IsStatic*/isStatic, introducer,
4061-
/*IsCaptureList*/false,
40624056
Impl.importSourceLoc(decl->getLocation()),
40634057
name, dc);
40644058
result->setIsObjC(false);
@@ -5234,8 +5228,7 @@ namespace {
52345228
auto result = Impl.createDeclWithClangNode<VarDecl>(decl,
52355229
getOverridableAccessLevel(dc),
52365230
/*IsStatic*/decl->isClassProperty(), VarDecl::Introducer::Var,
5237-
/*IsCaptureList*/false, Impl.importSourceLoc(decl->getLocation()),
5238-
name, dc);
5231+
Impl.importSourceLoc(decl->getLocation()), name, dc);
52395232
result->setInterfaceType(type);
52405233
Impl.recordImplicitUnwrapForDecl(result,
52415234
importedType.isImplicitlyUnwrapped());
@@ -6159,7 +6152,7 @@ SwiftDeclConverter::getImplicitProperty(ImportedName importedName,
61596152

61606153
auto property = Impl.createDeclWithClangNode<VarDecl>(
61616154
getter, AccessLevel::Public, /*IsStatic*/isStatic,
6162-
VarDecl::Introducer::Var, /*IsCaptureList*/false, SourceLoc(),
6155+
VarDecl::Introducer::Var, SourceLoc(),
61636156
propertyName, dc);
61646157
property->setInterfaceType(swiftPropertyType);
61656158
property->setIsObjC(false);
@@ -8575,12 +8568,11 @@ ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc,
85758568
var = createDeclWithClangNode<VarDecl>(ClangN, AccessLevel::Public,
85768569
/*IsStatic*/isStatic,
85778570
VarDecl::Introducer::Var,
8578-
/*IsCaptureList*/false, SourceLoc(),
8579-
name, dc);
8571+
SourceLoc(), name, dc);
85808572
} else {
85818573
var = new (SwiftContext)
85828574
VarDecl(/*IsStatic*/isStatic, VarDecl::Introducer::Var,
8583-
/*IsCaptureList*/false, SourceLoc(), name, dc);
8575+
SourceLoc(), name, dc);
85848576
}
85858577

85868578
var->setInterfaceType(type);
@@ -8641,7 +8633,6 @@ createUnavailableDecl(Identifier name, DeclContext *dc, Type type,
86418633
auto var = createDeclWithClangNode<VarDecl>(ClangN, AccessLevel::Public,
86428634
/*IsStatic*/isStatic,
86438635
VarDecl::Introducer::Var,
8644-
/*IsCaptureList*/false,
86458636
SourceLoc(), name, dc);
86468637
var->setIsObjC(false);
86478638
var->setIsDynamic(false);

lib/Parse/ParseDecl.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5719,7 +5719,6 @@ Parser::parseDeclVarGetSet(Pattern *pattern, ParseDeclOptions Flags,
57195719
if (!storage) {
57205720
storage = new (Context) VarDecl(StaticLoc.isValid(),
57215721
VarDecl::Introducer::Var,
5722-
/*is capture list*/ false,
57235722
VarLoc, Identifier(),
57245723
CurDeclContext);
57255724
storage->setImplicit(true);

lib/Parse/ParseExpr.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1990,7 +1990,7 @@ ParserResult<Expr> Parser::parseExprStringLiteral() {
19901990
// Make the variable which will contain our temporary value.
19911991
auto InterpolationVar =
19921992
new (Context) VarDecl(/*IsStatic=*/false, VarDecl::Introducer::Var,
1993-
/*IsCaptureList=*/false, /*NameLoc=*/SourceLoc(),
1993+
/*NameLoc=*/SourceLoc(),
19941994
Context.Id_dollarInterpolation, CurDeclContext);
19951995
InterpolationVar->setImplicit(true);
19961996
InterpolationVar->setHasNonPatternBindingInit(true);
@@ -2573,7 +2573,6 @@ parseClosureSignatureIfPresent(SourceRange &bracketRange,
25732573
? VarDecl::Introducer::Let
25742574
: VarDecl::Introducer::Var);
25752575
auto *VD = new (Context) VarDecl(/*isStatic*/false, introducer,
2576-
/*isCaptureList*/true,
25772576
nameLoc, name, CurDeclContext);
25782577

25792578
// If we captured something under the name "self", remember that.
@@ -2592,9 +2591,10 @@ parseClosureSignatureIfPresent(SourceRange &bracketRange,
25922591
/*VarLoc*/ nameLoc, pattern, /*EqualLoc*/ equalLoc, initializer,
25932592
CurDeclContext);
25942593

2595-
auto CLE = CaptureListEntry(VD, PBD);
2596-
if (CLE.isSimpleSelfCapture())
2597-
VD->setIsSelfParamCapture();
2594+
auto CLE = CaptureListEntry(VD, PBD);
2595+
if (CLE.isSimpleSelfCapture())
2596+
VD->setIsSelfParamCapture();
2597+
25982598
captureList.push_back(CLE);
25992599
} while (HasNext);
26002600

lib/Parse/ParsePattern.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -965,7 +965,7 @@ ParserResult<Pattern> Parser::parsePattern() {
965965
SF.Kind == SourceFileKind::Interface) {
966966
PatternCtx.setCreateSyntax(SyntaxKind::IdentifierPattern);
967967
auto VD = new (Context) VarDecl(
968-
/*IsStatic*/false, introducer, /*IsCaptureList*/false,
968+
/*IsStatic*/false, introducer,
969969
consumeToken(tok::kw__), Identifier(), CurDeclContext);
970970
return makeParserResult(NamedPattern::createImplicit(Context, VD));
971971
}
@@ -1038,8 +1038,7 @@ ParserResult<Pattern> Parser::parsePattern() {
10381038
Pattern *Parser::createBindingFromPattern(SourceLoc loc, Identifier name,
10391039
VarDecl::Introducer introducer) {
10401040
auto var = new (Context) VarDecl(/*IsStatic*/false, introducer,
1041-
/*IsCaptureList*/false, loc, name,
1042-
CurDeclContext);
1041+
loc, name, CurDeclContext);
10431042
return new (Context) NamedPattern(var);
10441043
}
10451044

lib/Parse/ParseStmt.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,7 +1087,7 @@ static void parseGuardedPattern(Parser &P, GuardedPattern &result,
10871087
auto errorName = P.Context.Id_error;
10881088
auto var = new (P.Context) VarDecl(/*IsStatic*/false,
10891089
VarDecl::Introducer::Let,
1090-
/*IsCaptureList*/false, loc, errorName,
1090+
loc, errorName,
10911091
P.CurDeclContext);
10921092
var->setImplicit();
10931093
auto namePattern = new (P.Context) NamedPattern(var);
@@ -2032,7 +2032,7 @@ ParserResult<CaseStmt> Parser::parseStmtCatch() {
20322032
for (unsigned i : indices(tmp)) {
20332033
auto *vOld = tmp[i];
20342034
auto *vNew = new (Context) VarDecl(
2035-
/*IsStatic*/ false, vOld->getIntroducer(), false /*IsCaptureList*/,
2035+
/*IsStatic*/ false, vOld->getIntroducer(),
20362036
vOld->getNameLoc(), vOld->getName(), vOld->getDeclContext());
20372037
vNew->setHasNonPatternBindingInit();
20382038
vNew->setImplicit();
@@ -2379,7 +2379,7 @@ parseStmtCase(Parser &P, SourceLoc &CaseLoc,
23792379
for (unsigned i : indices(tmp)) {
23802380
auto *vOld = tmp[i];
23812381
auto *vNew = new (P.Context) VarDecl(
2382-
/*IsStatic*/ false, vOld->getIntroducer(), false /*IsCaptureList*/,
2382+
/*IsStatic*/ false, vOld->getIntroducer(),
23832383
vOld->getNameLoc(), vOld->getName(), vOld->getDeclContext());
23842384
vNew->setHasNonPatternBindingInit();
23852385
vNew->setImplicit();

lib/SILOptimizer/Differentiation/LinearMapInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ VarDecl *LinearMapInfo::addVarDecl(NominalTypeDecl *nominal, StringRef name,
7575
auto &astCtx = nominal->getASTContext();
7676
auto id = astCtx.getIdentifier(name);
7777
auto *varDecl = new (astCtx) VarDecl(
78-
/*IsStatic*/ false, VarDecl::Introducer::Var, /*IsCaptureList*/ false,
78+
/*IsStatic*/ false, VarDecl::Introducer::Var,
7979
SourceLoc(), id, nominal);
8080
varDecl->setAccess(nominal->getEffectiveAccess());
8181
if (type->hasArchetype())

0 commit comments

Comments
 (0)