Skip to content

Commit a23d39b

Browse files
committed
[Macros] Mangle attached macro expansions based only on syntactic information
The mangling of attached macro expansions based on the declaration to which they are attached requires semantic information (specifically, the interface type of that declaration) that caused cyclic dependencies during type checking. Replace the mangling with a less-complete mangling that only requires syntactic information from the declaration, i.e., the name of the declaration to which the macro was attached. This eliminates reference cycles that occur with attached macros that produce arbitrary names.
1 parent 153c9d2 commit a23d39b

File tree

12 files changed

+135
-70
lines changed

12 files changed

+135
-70
lines changed

docs/ABI/Mangling.rst

+6-6
Original file line numberDiff line numberDiff line change
@@ -396,13 +396,13 @@ Entities
396396

397397
macro-discriminator-list ::= macro-discriminator-list? file-discriminator? macro-expansion-operator INDEX
398398

399-
macro-expansion-operator ::= identifier 'fMa' // attached accessor macro
400-
macro-expansion-operator ::= identifier 'fMA' // attached member-attribute macro
399+
macro-expansion-operator ::= decl-name identifier 'fMa' // attached accessor macro
400+
macro-expansion-operator ::= decl-name identifier 'fMA' // attached member-attribute macro
401401
macro-expansion-operator ::= identifier 'fMf' // freestanding macro
402-
macro-expansion-operator ::= identifier 'fMm' // attached member macro
403-
macro-expansion-operator ::= identifier 'fMp' // attached peer macro
404-
macro-expansion-operator ::= identifier 'fMc' // attached conformance macro
405-
macro-expansion-operator ::= identifier 'fMu' // uniquely-named entity
402+
macro-expansion-operator ::= decl-name identifier 'fMm' // attached member macro
403+
macro-expansion-operator ::= decl-name identifier 'fMp' // attached peer macro
404+
macro-expansion-operator ::= decl-name identifier 'fMc' // attached conformance macro
405+
macro-expansion-operator ::= decl-name identifier 'fMu' // uniquely-named entity
406406

407407
file-discriminator ::= identifier 'Ll' // anonymous file-discriminated declaration
408408

include/swift/AST/ASTMangler.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,8 @@ class ASTMangler : public Mangler {
401401
void appendType(Type type, GenericSignature sig,
402402
const ValueDecl *forDecl = nullptr);
403403

404-
void appendDeclName(const ValueDecl *decl);
404+
void appendDeclName(
405+
const ValueDecl *decl, DeclBaseName name = DeclBaseName());
405406

406407
GenericTypeParamType *appendAssocType(DependentMemberType *DepTy,
407408
GenericSignature sig,

lib/AST/ASTMangler.cpp

+25-9
Original file line numberDiff line numberDiff line change
@@ -1006,8 +1006,9 @@ static Optional<std::string> getOverriddenSwiftProtocolObjCName(
10061006
return None;
10071007
}
10081008

1009-
void ASTMangler::appendDeclName(const ValueDecl *decl) {
1010-
DeclBaseName name = decl->getBaseName();
1009+
void ASTMangler::appendDeclName(const ValueDecl *decl, DeclBaseName name) {
1010+
if (name.empty())
1011+
name = decl->getBaseName();
10111012
assert(!name.isSpecial() && "Cannot print special names");
10121013

10131014
auto *synthesizedTypeAttr =
@@ -4022,28 +4023,43 @@ std::string ASTMangler::mangleAttachedMacroExpansion(
40224023
const Decl *decl, CustomAttr *attr, MacroRole role) {
40234024
beginMangling();
40244025

4026+
// Append the context and name of the declaration.
4027+
// We don't mangle the declaration itself because doing so requires semantic
4028+
// information (e.g., its interface type), which introduces cyclic
4029+
// dependencies.
40254030
const Decl *attachedTo = decl;
4031+
DeclBaseName attachedToName;
40264032
if (auto valueDecl = dyn_cast<ValueDecl>(decl)) {
4027-
if (role != MacroRole::MemberAttribute) {
4028-
appendAnyDecl(valueDecl);
4029-
} else {
4030-
// Appending the member would result in a cycle since `VarDecl` appends
4031-
// its type, which would then loop back around to getting the attributes
4032-
// again. We'll instead add a discriminator for each member.
4033-
appendContextOf(valueDecl);
4033+
appendContextOf(valueDecl);
4034+
4035+
// Mangle the name, replacing special names with their user-facing names.
4036+
attachedToName = valueDecl->getName().getBaseName();
4037+
if (attachedToName.isSpecial()) {
4038+
attachedToName =
4039+
decl->getASTContext().getIdentifier(attachedToName.userFacingName());
4040+
}
4041+
appendDeclName(valueDecl, attachedToName);
4042+
4043+
// For member attribute macros, the attribute is attached to the enclosing
4044+
// declaration.
4045+
if (role == MacroRole::MemberAttribute) {
40344046
attachedTo = decl->getDeclContext()->getAsDecl();
40354047
}
40364048
} else {
40374049
appendContext(decl->getDeclContext(), "");
4050+
appendIdentifier("_");
40384051
}
40394052

4053+
// Determine the name of the macro.
40404054
DeclBaseName macroName;
40414055
if (auto *macroDecl = attachedTo->getResolvedMacro(attr)) {
40424056
macroName = macroDecl->getName().getBaseName();
40434057
} else {
40444058
macroName = decl->getASTContext().getIdentifier("__unknown_macro__");
40454059
}
40464060

4061+
// FIXME: attached macro discriminators should take attachedToName into
4062+
// account.
40474063
appendMacroExpansionOperator(
40484064
macroName.userFacingName(), role,
40494065
decl->getAttachedMacroDiscriminator(macroName, role, attr));

lib/Demangling/Demangler.cpp

+31-4
Original file line numberDiff line numberDiff line change
@@ -4061,47 +4061,74 @@ static bool isMacroExpansionNodeKind(Node::Kind kind) {
40614061

40624062
NodePointer Demangler::demangleMacroExpansion() {
40634063
Node::Kind kind;
4064+
bool isAttached;
4065+
bool isFreestanding;
40644066
switch (nextChar()) {
40654067
case 'a':
40664068
kind = Node::Kind::AccessorAttachedMacroExpansion;
4069+
isAttached = true;
4070+
isFreestanding = false;
40674071
break;
40684072

40694073
case 'A':
40704074
kind = Node::Kind::MemberAttributeAttachedMacroExpansion;
4075+
isAttached = true;
4076+
isFreestanding = false;
40714077
break;
40724078

40734079
case 'f':
40744080
kind = Node::Kind::FreestandingMacroExpansion;
4081+
isAttached = false;
4082+
isFreestanding = true;
40754083
break;
40764084

40774085
case 'm':
40784086
kind = Node::Kind::MemberAttachedMacroExpansion;
4087+
isAttached = true;
4088+
isFreestanding = false;
40794089
break;
40804090

40814091
case 'p':
40824092
kind = Node::Kind::PeerAttachedMacroExpansion;
4093+
isAttached = true;
4094+
isFreestanding = false;
40834095
break;
40844096

40854097
case 'c':
40864098
kind = Node::Kind::ConformanceAttachedMacroExpansion;
4099+
isAttached = true;
4100+
isFreestanding = false;
40874101
break;
40884102

40894103
case 'u':
40904104
kind = Node::Kind::MacroExpansionUniqueName;
4105+
isAttached = false;
4106+
isFreestanding = false;
40914107
break;
40924108

40934109
default:
40944110
return nullptr;
40954111
}
40964112

4097-
NodePointer name = popNode(Node::Kind::Identifier);
4098-
NodePointer privateDiscriminator = popNode(Node::Kind::PrivateDeclName);
4113+
NodePointer macroName = popNode(Node::Kind::Identifier);
4114+
NodePointer privateDiscriminator = nullptr;
4115+
if (isFreestanding)
4116+
privateDiscriminator = popNode(Node::Kind::PrivateDeclName);
4117+
NodePointer attachedName = nullptr;
4118+
if (isAttached)
4119+
attachedName = popNode(isDeclName);
4120+
40994121
NodePointer context = popNode(isMacroExpansionNodeKind);
41004122
if (!context)
41014123
context = popContext();
41024124
NodePointer discriminator = demangleIndexAsNode();
4103-
auto result = createWithChildren(
4104-
kind, context, name, discriminator);
4125+
NodePointer result;
4126+
if (isAttached) {
4127+
result = createWithChildren(
4128+
kind, context, attachedName, macroName, discriminator);
4129+
} else {
4130+
result = createWithChildren(kind, context, macroName, discriminator);
4131+
}
41054132
if (privateDiscriminator)
41064133
result->addChild(privateDiscriminator, *this);
41074134
return result;

lib/Demangling/NodePrinter.cpp

+20-10
Original file line numberDiff line numberDiff line change
@@ -1434,28 +1434,38 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth,
14341434
/*hasName*/ true);
14351435
case Node::Kind::AccessorAttachedMacroExpansion:
14361436
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
1437-
/*hasName*/true, "accessor macro expansion #",
1438-
(int)Node->getChild(2)->getIndex() + 1);
1437+
/*hasName*/true,
1438+
("accessor macro @" +
1439+
nodeToString(Node->getChild(2)) + " expansion #"),
1440+
(int)Node->getChild(3)->getIndex() + 1);
14391441
case Node::Kind::FreestandingMacroExpansion:
14401442
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
14411443
/*hasName*/true, "freestanding macro expansion #",
14421444
(int)Node->getChild(2)->getIndex() + 1);
14431445
case Node::Kind::MemberAttributeAttachedMacroExpansion:
14441446
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
1445-
/*hasName*/true, "member attribute macro expansion #",
1446-
(int)Node->getChild(2)->getIndex() + 1);
1447+
/*hasName*/true,
1448+
("member attribute macro @" +
1449+
nodeToString(Node->getChild(2)) + " expansion #"),
1450+
(int)Node->getChild(3)->getIndex() + 1);
14471451
case Node::Kind::MemberAttachedMacroExpansion:
14481452
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
1449-
/*hasName*/true, "member macro expansion #",
1450-
(int)Node->getChild(2)->getIndex() + 1);
1453+
/*hasName*/true,
1454+
("member macro @" + nodeToString(Node->getChild(2)) +
1455+
" expansion #"),
1456+
(int)Node->getChild(3)->getIndex() + 1);
14511457
case Node::Kind::PeerAttachedMacroExpansion:
14521458
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
1453-
/*hasName*/true, "peer macro expansion #",
1454-
(int)Node->getChild(2)->getIndex() + 1);
1459+
/*hasName*/true,
1460+
("peer macro @" + nodeToString(Node->getChild(2)) +
1461+
" expansion #"),
1462+
(int)Node->getChild(3)->getIndex() + 1);
14551463
case Node::Kind::ConformanceAttachedMacroExpansion:
14561464
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
1457-
/*hasName*/true, "conformance macro expansion #",
1458-
(int)Node->getChild(2)->getIndex() + 1);
1465+
/*hasName*/true,
1466+
("conformance macro @" + nodeToString(Node->getChild(2)) +
1467+
" expansion #"),
1468+
(int)Node->getChild(3)->getIndex() + 1);
14591469
case Node::Kind::MacroExpansionUniqueName:
14601470
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
14611471
/*hasName*/true, "unique name #",

lib/Demangling/Remangler.cpp

+10-15
Original file line numberDiff line numberDiff line change
@@ -2908,51 +2908,46 @@ ManglingError Remangler::mangleFreestandingMacroExpansion(
29082908
ManglingError Remangler::mangleAccessorAttachedMacroExpansion(
29092909
Node *node, unsigned depth) {
29102910
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1));
2911-
if (auto privateDiscriminator = node->getChild(3))
2912-
RETURN_IF_ERROR(mangle(privateDiscriminator, depth + 1));
29132911
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
2912+
RETURN_IF_ERROR(mangleChildNode(node, 2, depth + 1));
29142913
Buffer << "fMa";
2915-
return mangleChildNode(node, 2, depth + 1);
2914+
return mangleChildNode(node, 3, depth + 1);
29162915
}
29172916

29182917
ManglingError Remangler::mangleMemberAttributeAttachedMacroExpansion(
29192918
Node *node, unsigned depth) {
29202919
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1));
2921-
if (auto privateDiscriminator = node->getChild(3))
2922-
RETURN_IF_ERROR(mangle(privateDiscriminator, depth + 1));
29232920
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
2921+
RETURN_IF_ERROR(mangleChildNode(node, 2, depth + 1));
29242922
Buffer << "fMA";
2925-
return mangleChildNode(node, 2, depth + 1);
2923+
return mangleChildNode(node, 3, depth + 1);
29262924
}
29272925

29282926
ManglingError Remangler::mangleMemberAttachedMacroExpansion(
29292927
Node *node, unsigned depth) {
29302928
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1));
2931-
if (auto privateDiscriminator = node->getChild(3))
2932-
RETURN_IF_ERROR(mangle(privateDiscriminator, depth + 1));
29332929
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
2930+
RETURN_IF_ERROR(mangleChildNode(node, 2, depth + 1));
29342931
Buffer << "fMm";
2935-
return mangleChildNode(node, 2, depth + 1);
2932+
return mangleChildNode(node, 3, depth + 1);
29362933
}
29372934

29382935
ManglingError Remangler::manglePeerAttachedMacroExpansion(
29392936
Node *node, unsigned depth) {
29402937
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1));
2941-
if (auto privateDiscriminator = node->getChild(3))
2942-
RETURN_IF_ERROR(mangle(privateDiscriminator, depth + 1));
29432938
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
2939+
RETURN_IF_ERROR(mangleChildNode(node, 2, depth + 1));
29442940
Buffer << "fMp";
2945-
return mangleChildNode(node, 2, depth + 1);
2941+
return mangleChildNode(node, 3, depth + 1);
29462942
}
29472943

29482944
ManglingError Remangler::mangleConformanceAttachedMacroExpansion(
29492945
Node *node, unsigned depth) {
29502946
RETURN_IF_ERROR(mangleChildNode(node, 0, depth + 1));
2951-
if (auto privateDiscriminator = node->getChild(3))
2952-
RETURN_IF_ERROR(mangle(privateDiscriminator, depth + 1));
29532947
RETURN_IF_ERROR(mangleChildNode(node, 1, depth + 1));
2948+
RETURN_IF_ERROR(mangleChildNode(node, 2, depth + 1));
29542949
Buffer << "fMc";
2955-
return mangleChildNode(node, 2, depth + 1);
2950+
return mangleChildNode(node, 3, depth + 1);
29562951
}
29572952

29582953
ManglingError Remangler::mangleMacroExpansionUniqueName(

test/Demangle/Inputs/manglings.txt

+1-3
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,5 @@ $s4main4TestVAA3ABCV4hereyySiFfa ---> runtime attribute generator of main.ABC.he
454454
$s9MacroUser13testStringify1a1bySi_SitF9stringifyfMf1_ ---> freestanding macro expansion #3 of stringify in MacroUser.testStringify(a: Swift.Int, b: Swift.Int) -> ()
455455
$s9MacroUser016testFreestandingA9ExpansionyyF4Foo3L_V23bitwidthNumberedStructsfMf_6methodfMu0_ ---> unique name #2 of method in freestanding macro expansion #1 of bitwidthNumberedStructs in Foo3 #1 in MacroUser.testFreestandingMacroExpansion() -> ()
456456
@__swiftmacro_1a13testStringifyAA1bySi_SitF9stringifyfMf_ ---> freestanding macro expansion #1 of stringify in a.testStringify(a: Swift.Int, b: Swift.Int) -> ()
457-
@__swiftmacro_15accessor_macros8MyStructV4nameSSvp17myPropertyWrapperfMa_ ---> accessor macro expansion #1 of myPropertyWrapper in accessor_macros.MyStruct.name : Swift.String
458-
@__swiftmacro_18macro_expand_peers1SV1f1a3for_SSSi_SSSdtYaF20addCompletionHandlerfMp_ ---> peer macro expansion #1 of addCompletionHandler in macro_expand_peers.S.f(a: Swift.Int, for: Swift.String, _: Swift.Double) async -> Swift.String
459-
@__swiftmacro_25macro_expand_conformances7GenericV20DelegatedConformancefMc_ ---> conformance macro expansion #1 of DelegatedConformance in macro_expand_conformances.Generic
457+
@__swiftmacro_18macro_expand_peers1SV1f20addCompletionHandlerfMp_ ---> peer macro @addCompletionHandler expansion #1 of f in macro_expand_peers.S
460458
@__swiftmacro_9MacroUser16MemberNotCoveredV33_4361AD9339943F52AE6186DD51E04E91Ll0dE0fMf0_ ---> freestanding macro expansion #2 of NotCovered(in _4361AD9339943F52AE6186DD51E04E91) in MacroUser.MemberNotCovered

test/Macros/accessor_macros.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ struct MyStruct {
4343

4444
@myPropertyWrapper
4545
var name: String
46-
// CHECK-DUMP: @__swiftmacro_15accessor_macros8MyStructV4nameSSvp17myPropertyWrapperfMa_.swift
46+
// CHECK-DUMP: @__swiftmacro_15accessor_macros8MyStructV4name17myPropertyWrapperfMa_.swift
4747
// CHECK-DUMP: get {
4848
// CHECK-DUMP: _name.wrappedValue
4949
// CHECK-DUMP: }
@@ -53,7 +53,7 @@ struct MyStruct {
5353

5454
@myPropertyWrapper
5555
var birthDate: Date?
56-
// CHECK-DUMP: @__swiftmacro_15accessor_macros8MyStructV9birthDateAA0F0VSgvp17myPropertyWrapperfMa_.swift
56+
// CHECK-DUMP: @__swiftmacro_15accessor_macros8MyStructV9birthDate17myPropertyWrapperfMa_.swift
5757
// CHECK-DUMP: get {
5858
// CHECK-DUMP: _birthDate.wrappedValue
5959
// CHECK-DUMP: }

test/Macros/macro_expand.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ struct Bad {}
6767
// CHECK-DIAGS: error: macro expansion cannot introduce default literal type '_ImageLiteralType'
6868
// CHECK-DIAGS: error: macro expansion cannot introduce default literal type '_FileReferenceLiteralType'
6969

70-
// CHECK-DIAGS: CONTENTS OF FILE @__swiftmacro_9MacroUser3BadV7InvalidfMp_.swift
70+
// CHECK-DIAGS: CONTENTS OF FILE @__swiftmacro_9MacroUser3Bad7InvalidfMp_.swift
7171
// CHECK-DIAGS: import Swift
7272
// CHECK-DIAGS: precedencegroup MyPrecedence {}
7373
// CHECK-DIAGS: @attached(member) macro myMacro()

test/Macros/macro_expand_conformances.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ struct S {}
2929
@Hashable
3030
struct S2 {}
3131

32-
// CHECK-DUMP: @__swiftmacro_25macro_expand_conformances1SV9EquatablefMc_.swift
32+
// CHECK-DUMP: @__swiftmacro_25macro_expand_conformances1S9EquatablefMc_.swift
3333
// CHECK-DUMP: extension S : Equatable {}
3434

3535
// CHECK: true
@@ -55,7 +55,7 @@ struct Wrapped: P {
5555
@DelegatedConformance
5656
struct Generic<Element> {}
5757

58-
// CHECK-DUMP: @__swiftmacro_25macro_expand_conformances7GenericV20DelegatedConformancefMc_.swift
58+
// CHECK-DUMP: @__swiftmacro_25macro_expand_conformances7Generic20DelegatedConformancefMc_.swift
5959
// CHECK-DUMP: extension Generic : P where Element: P {}
6060

6161
func requiresP(_ value: (some P).Type) {

0 commit comments

Comments
 (0)