Skip to content

Commit c3fbc6e

Browse files
committed
Introduce a new Initializer subclass for the arguments of custom attributes
Since the introduction of custom attributes (as part of property wrappers), we've modeled the context of expressions within these attributes as PatternBindingInitializers. These PatternBindingInitializers would get wired in to the variable declarations they apply to, establishing the appropriate declaration context hierarchy. This worked because property wrappers only every applied to---you guessed it!---properties, so the PatternBindingInitializer would always get filled in. When custom attributes were extended to apply to anything for the purposes of macros, the use of PatternBindingInitializer became less appropriate. Specifically, the binding declaration would never get filled in (it's always NULL), so any place in the compiler that accesses the binding might have to deal with it being NULL, which is a new requirement. Few did, crashes ensued. Rather than continue to play whack-a-mole with the abused PatternBindingInitializer, introduce a new CustomAttributeInitializer to model the context of custom attribute arguments. When the attributes are assigned to a declaration that has a PatternBindingInitializer, we reparent this new initializer to the PatternBindingInitializer. This helps separate out the logic for custom attributes vs. actual initializers. Fixes #76409 / rdar://136997841
1 parent f1a10a0 commit c3fbc6e

21 files changed

+160
-74
lines changed

include/swift/AST/ASTBridging.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,14 @@ SWIFT_NAME("getter:BridgedPatternBindingInitializer.asDeclContext(self:)")
533533
BridgedDeclContext BridgedPatternBindingInitializer_asDeclContext(
534534
BridgedPatternBindingInitializer cInit);
535535

536+
SWIFT_NAME("BridgedCustomAttributeInitializer.create(declContext:)")
537+
BridgedCustomAttributeInitializer
538+
BridgedCustomAttributeInitializer_create(BridgedDeclContext cDeclContext);
539+
540+
SWIFT_NAME("getter:BridgedCustomAttributeInitializer.asDeclContext(self:)")
541+
BridgedDeclContext BridgedCustomAttributeInitializer_asDeclContext(
542+
BridgedCustomAttributeInitializer cInit);
543+
536544
SWIFT_NAME("getter:BridgedClosureExpr.asDeclContext(self:)")
537545
BridgedDeclContext
538546
BridgedClosureExpr_asDeclContext(BridgedClosureExpr cClosure);
@@ -609,7 +617,7 @@ SWIFT_NAME(
609617
"BridgedCustomAttr.createParsed(_:atLoc:type:initContext:argumentList:)")
610618
BridgedCustomAttr BridgedCustomAttr_createParsed(
611619
BridgedASTContext cContext, BridgedSourceLoc cAtLoc, BridgedTypeRepr cType,
612-
BridgedNullablePatternBindingInitializer cInitContext,
620+
BridgedNullableCustomAttributeInitializer cInitContext,
613621
BridgedNullableArgumentList cArgumentList);
614622

615623
SWIFT_NAME(

include/swift/AST/ASTBridgingWrappers.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ AST_BRIDGING_WRAPPER_NULLABLE(GenericParamList)
8383
AST_BRIDGING_WRAPPER_NULLABLE(TrailingWhereClause)
8484
AST_BRIDGING_WRAPPER_NULLABLE(ParameterList)
8585
AST_BRIDGING_WRAPPER_NULLABLE(PatternBindingInitializer)
86+
AST_BRIDGING_WRAPPER_NULLABLE(CustomAttributeInitializer)
8687
AST_BRIDGING_WRAPPER_NONNULL(TypeAttributes)
8788
AST_BRIDGING_WRAPPER_NONNULL(CustomAttribute)
8889
AST_BRIDGING_WRAPPER_NULLABLE(ArgumentList)

include/swift/AST/Attr.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class AbstractFunctionDecl;
6060
class FuncDecl;
6161
class ClassDecl;
6262
class AccessorDecl;
63+
class CustomAttributeInitializer;
6364
class GenericFunctionType;
6465
class LazyConformanceLoader;
6566
class LazyMemberLoader;
@@ -1846,13 +1847,13 @@ class ClangImporterSynthesizedTypeAttr : public DeclAttribute {
18461847
class CustomAttr final : public DeclAttribute {
18471848
TypeExpr *typeExpr;
18481849
ArgumentList *argList;
1849-
PatternBindingInitializer *initContext;
1850+
CustomAttributeInitializer *initContext;
18501851
Expr *semanticInit = nullptr;
18511852

18521853
mutable unsigned isArgUnsafeBit : 1;
18531854

18541855
CustomAttr(SourceLoc atLoc, SourceRange range, TypeExpr *type,
1855-
PatternBindingInitializer *initContext, ArgumentList *argList,
1856+
CustomAttributeInitializer *initContext, ArgumentList *argList,
18561857
bool implicit);
18571858

18581859
public:
@@ -1863,7 +1864,7 @@ class CustomAttr final : public DeclAttribute {
18631864
}
18641865

18651866
static CustomAttr *create(ASTContext &ctx, SourceLoc atLoc, TypeExpr *type,
1866-
PatternBindingInitializer *initContext,
1867+
CustomAttributeInitializer *initContext,
18671868
ArgumentList *argList, bool implicit = false);
18681869

18691870
TypeExpr *getTypeExpr() const { return typeExpr; }
@@ -1896,7 +1897,7 @@ class CustomAttr final : public DeclAttribute {
18961897
Expr *getSemanticInit() const { return semanticInit; }
18971898
void setSemanticInit(Expr *expr) { semanticInit = expr; }
18981899

1899-
PatternBindingInitializer *getInitContext() const { return initContext; }
1900+
CustomAttributeInitializer *getInitContext() const { return initContext; }
19001901

19011902
static bool classof(const DeclAttribute *DA) {
19021903
return DA->getKind() == DeclAttrKind::Custom;
@@ -3064,6 +3065,10 @@ class DeclAttributes {
30643065
const_cast<const DeclAttributes *>(this)->getEffectiveSendableAttr());
30653066
}
30663067

3068+
/// Try to find the custom attribute initializer within the list of
3069+
/// attributes.
3070+
CustomAttributeInitializer *findCustomAttributeInitializer() const;
3071+
30673072
public:
30683073
template <typename ATTR, bool AllowInvalid>
30693074
using AttributeKindRange =

include/swift/AST/Initializer.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222

2323
#include "swift/AST/DeclContext.h"
2424

25+
namespace llvm {
26+
class raw_ostream;
27+
}
28+
2529
namespace swift {
2630
class ParamDecl;
2731
class PatternBindingDecl;
@@ -36,6 +40,9 @@ enum class InitializerKind : uint8_t {
3640

3741
/// A property wrapper initialization expression.
3842
PropertyWrapper,
43+
44+
/// An expression within a custom attribute.
45+
CustomAttribute,
3946
};
4047

4148
/// An Initializer is a kind of DeclContext used for expressions that
@@ -176,6 +183,34 @@ class PropertyWrapperInitializer : public Initializer {
176183
}
177184
};
178185

186+
/// An expression within a custom attribute. The parent context is the
187+
/// context in which the attributed declaration occurs.
188+
class CustomAttributeInitializer : public Initializer {
189+
public:
190+
explicit CustomAttributeInitializer(DeclContext *parent)
191+
: Initializer(InitializerKind::CustomAttribute, parent) {}
192+
193+
static CustomAttributeInitializer *create(DeclContext *parent) {
194+
return new (parent->getASTContext()) CustomAttributeInitializer(parent);
195+
}
196+
197+
void setEnclosingInitializer(Initializer *newParent) {
198+
setParent(newParent);
199+
}
200+
201+
static bool classof(const DeclContext *DC) {
202+
if (auto init = dyn_cast<Initializer>(DC))
203+
return classof(init);
204+
return false;
205+
}
206+
207+
static bool classof(const Initializer *I) {
208+
return I->getInitializerKind() == InitializerKind::CustomAttribute;
209+
}
210+
};
211+
212+
void simple_display(llvm::raw_ostream &out, Initializer *init);
213+
179214
} // end namespace swift
180215

181216
#endif

include/swift/Parse/Parser.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -999,7 +999,7 @@ class Parser {
999999
/// Parse an #if ... #endif containing only attributes.
10001000
ParserStatus parseIfConfigAttributes(
10011001
DeclAttributes &attributes, bool ifConfigsAreDeclAttrs,
1002-
PatternBindingInitializer *initContext);
1002+
CustomAttributeInitializer *&initContext);
10031003

10041004
/// Parse a #error or #warning diagnostic.
10051005
ParserResult<PoundDiagnosticDecl> parseDeclPoundDiagnostic();
@@ -1027,7 +1027,7 @@ class Parser {
10271027
/// This is the inner loop, which can be called recursively.
10281028
ParserStatus parseDeclAttributeList(DeclAttributes &Attributes,
10291029
bool IfConfigsAreDeclAttrs,
1030-
PatternBindingInitializer *initContext);
1030+
CustomAttributeInitializer *&initContext);
10311031

10321032
/// Parse the optional attributes before a closure declaration.
10331033
ParserStatus parseClosureDeclAttributeList(DeclAttributes &Attributes);
@@ -1163,7 +1163,7 @@ class Parser {
11631163
/// Parse a specific attribute.
11641164
ParserStatus parseDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
11651165
SourceLoc AtEndLoc,
1166-
PatternBindingInitializer *&initContext,
1166+
CustomAttributeInitializer *&initContext,
11671167
bool isFromClangAttribute = false);
11681168

11691169
bool isCustomAttributeArgument();
@@ -1178,7 +1178,7 @@ class Parser {
11781178
/// will get filled in by this function. The same variable should be provided
11791179
/// for every custom attribute within the same attribute list.
11801180
ParserResult<CustomAttr> parseCustomAttribute(
1181-
SourceLoc atLoc, PatternBindingInitializer *&initContext);
1181+
SourceLoc atLoc, CustomAttributeInitializer *&initContext);
11821182

11831183
ParserStatus parseNewDeclAttribute(DeclAttributes &Attributes,
11841184
SourceLoc AtLoc, DeclAttrKind DK,
@@ -1480,7 +1480,7 @@ class Parser {
14801480

14811481
ParserStatus parseTypeAttribute(TypeOrCustomAttr &result, SourceLoc AtLoc,
14821482
SourceLoc AtEndLoc, ParseTypeReason reason,
1483-
PatternBindingInitializer *&initContext,
1483+
CustomAttributeInitializer *&initContext,
14841484
bool justChecking = false);
14851485

14861486
ParserResult<TypeRepr> parseOldStyleProtocolComposition();

lib/AST/ASTDumper.cpp

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1809,17 +1809,7 @@ void swift::printContext(raw_ostream &os, DeclContext *dc) {
18091809
break;
18101810

18111811
case DeclContextKind::Initializer:
1812-
switch (cast<Initializer>(dc)->getInitializerKind()) {
1813-
case InitializerKind::PatternBinding:
1814-
os << "pattern binding initializer";
1815-
break;
1816-
case InitializerKind::DefaultArgument:
1817-
os << "default argument initializer";
1818-
break;
1819-
case InitializerKind::PropertyWrapper:
1820-
os << "property wrapper initializer";
1821-
break;
1822-
}
1812+
simple_display(os, cast<Initializer>(dc));
18231813
break;
18241814

18251815
case DeclContextKind::TopLevelCodeDecl:

lib/AST/ASTMangler.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2540,6 +2540,12 @@ void ASTMangler::appendContext(const DeclContext *ctx,
25402540
}
25412541
return;
25422542
}
2543+
2544+
case InitializerKind::CustomAttribute: {
2545+
BaseEntitySignature nullBase(nullptr);
2546+
appendContext(ctx->getParent(), nullBase, useModuleName);
2547+
return;
2548+
}
25432549
}
25442550
llvm_unreachable("bad initializer kind");
25452551
}

lib/AST/Attr.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2899,7 +2899,7 @@ ProtocolDecl *ImplementsAttr::getProtocol(DeclContext *dc) const {
28992899
}
29002900

29012901
CustomAttr::CustomAttr(SourceLoc atLoc, SourceRange range, TypeExpr *type,
2902-
PatternBindingInitializer *initContext,
2902+
CustomAttributeInitializer *initContext,
29032903
ArgumentList *argList, bool implicit)
29042904
: DeclAttribute(DeclAttrKind::Custom, atLoc, range, implicit),
29052905
typeExpr(type), argList(argList), initContext(initContext) {
@@ -2908,7 +2908,7 @@ CustomAttr::CustomAttr(SourceLoc atLoc, SourceRange range, TypeExpr *type,
29082908
}
29092909

29102910
CustomAttr *CustomAttr::create(ASTContext &ctx, SourceLoc atLoc, TypeExpr *type,
2911-
PatternBindingInitializer *initContext,
2911+
CustomAttributeInitializer *initContext,
29122912
ArgumentList *argList, bool implicit) {
29132913
assert(type);
29142914
SourceRange range(atLoc, type->getSourceRange().End);
@@ -3148,3 +3148,13 @@ bool swift::hasAttribute(const LangOptions &langOpts,
31483148

31493149
return false;
31503150
}
3151+
3152+
CustomAttributeInitializer *
3153+
DeclAttributes::findCustomAttributeInitializer() const {
3154+
for (auto custom : getAttributes<CustomAttr>()) {
3155+
if (auto initContext = custom->getInitContext())
3156+
return initContext;
3157+
}
3158+
3159+
return nullptr;
3160+
}

lib/AST/Bridging/DeclAttributeBridging.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ BridgedCDeclAttr BridgedCDeclAttr_createParsed(BridgedASTContext cContext,
132132

133133
BridgedCustomAttr BridgedCustomAttr_createParsed(
134134
BridgedASTContext cContext, BridgedSourceLoc cAtLoc, BridgedTypeRepr cType,
135-
BridgedNullablePatternBindingInitializer cInitContext,
135+
BridgedNullableCustomAttributeInitializer cInitContext,
136136
BridgedNullableArgumentList cArgumentList) {
137137
ASTContext &context = cContext.unbridged();
138138
return CustomAttr::create(

lib/AST/Bridging/DeclContextBridging.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ BridgedDeclContext BridgedPatternBindingInitializer_asDeclContext(
3131
return cInit.unbridged();
3232
}
3333

34+
BridgedCustomAttributeInitializer
35+
BridgedCustomAttributeInitializer_create(BridgedDeclContext cDeclContext) {
36+
return CustomAttributeInitializer::create(cDeclContext.unbridged());
37+
}
38+
39+
BridgedDeclContext BridgedCustomAttributeInitializer_asDeclContext(
40+
BridgedCustomAttributeInitializer cInit) {
41+
return cInit.unbridged();
42+
}
43+
3444
BridgedDeclContext
3545
BridgedClosureExpr_asDeclContext(BridgedClosureExpr cClosure) {
3646
return cClosure.unbridged();

lib/AST/Decl.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2061,9 +2061,18 @@ PatternBindingDecl::create(ASTContext &Ctx, SourceLoc StaticLoc,
20612061
// FIXME: We ought to reconsider this since it won't recontextualize any
20622062
// closures/decls present in the initialization expr. This currently should
20632063
// only affect implicit code though.
2064-
if (!initContext && !Parent->isLocalContext())
2064+
if (!initContext && !Parent->isLocalContext()) {
20652065
initContext = PatternBindingInitializer::create(Parent);
20662066

2067+
}
2068+
2069+
if (auto firstVar = PBD->getAnchoringVarDecl(idx)) {
2070+
if (auto attributeInit =
2071+
firstVar->getAttrs().findCustomAttributeInitializer()) {
2072+
attributeInit->setEnclosingInitializer(initContext);
2073+
}
2074+
}
2075+
20672076
// We need to call setPattern to ensure the VarDecls in the pattern have
20682077
// the PatternBindingDecl set as their parent. We also need to call
20692078
// setInitContext to setup the context.

lib/AST/DeclContext.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,9 @@ unsigned DeclContext::printContext(raw_ostream &OS, const unsigned indent,
869869
}
870870
break;
871871
}
872+
case InitializerKind::CustomAttribute:
873+
OS << " CustomAttribute";
874+
break;
872875
}
873876
break;
874877
}

lib/AST/TypeCheckRequests.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,6 +1470,9 @@ void swift::simple_display(llvm::raw_ostream &out, Initializer *init) {
14701470
case InitializerKind::PropertyWrapper:
14711471
out << "property wrapper initializer";
14721472
break;
1473+
case InitializerKind::CustomAttribute:
1474+
out << "custom attribute initializer";
1475+
break;
14731476
}
14741477
}
14751478

lib/ASTGen/Sources/ASTGen/Bridge.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ extension BridgedNullableGenericParamList: /*@retroactive*/ swiftASTGen.BridgedN
3434
extension BridgedNullableTrailingWhereClause: /*@retroactive*/ swiftASTGen.BridgedNullable {}
3535
extension BridgedNullableParameterList: /*@retroactive*/ swiftASTGen.BridgedNullable {}
3636
extension BridgedNullablePatternBindingInitializer: /*@retroactive*/ swiftASTGen.BridgedNullable {}
37+
extension BridgedNullableCustomAttributeInitializer: /*@retroactive*/ swiftASTGen.BridgedNullable {}
3738
extension BridgedNullableArgumentList: /*@retroactive*/ swiftASTGen.BridgedNullable {}
3839

3940
extension BridgedIdentifier: /*@retroactive*/ Swift.Equatable {
@@ -80,6 +81,9 @@ extension BridgedParameterList: BridgedHasNullable {
8081
extension BridgedPatternBindingInitializer: BridgedHasNullable {
8182
typealias Nullable = BridgedNullablePatternBindingInitializer
8283
}
84+
extension BridgedCustomAttributeInitializer: BridgedHasNullable {
85+
typealias Nullable = BridgedNullableCustomAttributeInitializer
86+
}
8387
extension BridgedArgumentList: BridgedHasNullable {
8488
typealias Nullable = BridgedNullableArgumentList
8589
}

lib/ASTGen/Sources/ASTGen/DeclAttrs.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ extension ASTGenVisitor {
2222
var attributes: BridgedDeclAttributes
2323
var staticSpelling: BridgedStaticSpelling
2424
var staticLoc: BridgedSourceLoc
25-
var initContext: BridgedPatternBindingInitializer?
25+
var initContext: BridgedCustomAttributeInitializer?
2626
}
2727

2828
func generateDeclAttributes(_ node: some WithAttributesSyntax & WithModifiersSyntax, allowStatic: Bool) -> DeclAttributesResult {
@@ -55,7 +55,7 @@ extension ASTGenVisitor {
5555
}
5656

5757
// '@' attributes.
58-
var initContext: BridgedPatternBindingInitializer? = nil
58+
var initContext: BridgedCustomAttributeInitializer? = nil
5959
visitIfConfigElements(node.attributes, of: AttributeSyntax.self) { element in
6060
switch element {
6161
case .ifConfigDecl(let ifConfigDecl):
@@ -99,7 +99,7 @@ extension ASTGenVisitor {
9999

100100
// MARK: - Decl attributes
101101
extension ASTGenVisitor {
102-
func generateDeclAttribute(attribute node: AttributeSyntax, initContext: inout BridgedPatternBindingInitializer?) -> BridgedDeclAttribute? {
102+
func generateDeclAttribute(attribute node: AttributeSyntax, initContext: inout BridgedCustomAttributeInitializer?) -> BridgedDeclAttribute? {
103103
if let identTy = node.attributeName.as(IdentifierTypeSyntax.self) {
104104
let attrName = identTy.name.rawText
105105
let attrKind = BridgedDeclAttrKind(from: attrName.bridged)
@@ -1119,7 +1119,7 @@ extension ASTGenVisitor {
11191119
)
11201120
}
11211121

1122-
func generateCustomAttr(attribute node: AttributeSyntax, initContext: inout BridgedPatternBindingInitializer?) -> BridgedCustomAttr? {
1122+
func generateCustomAttr(attribute node: AttributeSyntax, initContext: inout BridgedCustomAttributeInitializer?) -> BridgedCustomAttr? {
11231123
let type = self.generate(type: node.attributeName)
11241124

11251125
let argList: BridgedArgumentList?
@@ -1130,7 +1130,7 @@ extension ASTGenVisitor {
11301130
}
11311131

11321132
if !self.declContext.isLocalContext && initContext == nil {
1133-
initContext = BridgedPatternBindingInitializer.create(declContext: self.declContext)
1133+
initContext = BridgedCustomAttributeInitializer.create(declContext: self.declContext)
11341134
}
11351135
argList = withDeclContext(initContext?.asDeclContext ?? self.declContext) {
11361136
self.generateArgumentList(

lib/ASTGen/Sources/ASTGen/Decls.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ extension ASTGenVisitor {
472472
// ensures that property initializers are correctly treated as being in a
473473
// local context).
474474
if !self.declContext.isLocalContext {
475-
initContext = attrs.initContext ?? .create(declContext: self.declContext)
475+
initContext = .create(declContext: self.declContext)
476476
}
477477
initExpr = withDeclContext(initContext?.asDeclContext ?? self.declContext) {
478478
generate(expr: initializer.value)

lib/ASTGen/Sources/ASTGen/Exprs.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ extension ASTGenVisitor {
232232
return .underlying(attribute)
233233
}
234234
} body: { node in
235-
var initCtx: BridgedPatternBindingInitializer?
235+
var initCtx: BridgedCustomAttributeInitializer?
236236
if let attr = self.generateDeclAttribute(attribute: node, initContext: &initCtx) {
237237
result.attributes.add(attr)
238238
}

0 commit comments

Comments
 (0)