Skip to content

Commit a69c99d

Browse files
committed
[Macros] Implement attached extension macros.
1 parent bd11fce commit a69c99d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+325
-38
lines changed

include/swift/AST/MacroDeclaration.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ enum class MacroRole: uint32_t {
5858
/// A freestanding macro that expands to expressions, statements and
5959
/// declarations in a code block.
6060
CodeItem = 0x80,
61+
/// An attached macro that adds extensions to the declaration the
62+
/// macro is attached to.
63+
Extension = 0x100,
6164

6265
// NOTE: When adding a new macro role, also add it to `getAllMacroRoles`.
6366
};

include/swift/AST/TypeCheckRequests.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4053,6 +4053,28 @@ class ExpandConformanceMacros
40534053
void noteCycleStep(DiagnosticEngine &diags) const;
40544054
};
40554055

4056+
/// Expand all extension macros attached to the given declaration.
4057+
///
4058+
/// Produces the set of macro expansion buffer IDs.
4059+
class ExpandExtensionMacros
4060+
: public SimpleRequest<ExpandExtensionMacros,
4061+
ArrayRef<unsigned>(NominalTypeDecl *),
4062+
RequestFlags::Cached> {
4063+
public:
4064+
using SimpleRequest::SimpleRequest;
4065+
4066+
private:
4067+
friend SimpleRequest;
4068+
4069+
ArrayRef<unsigned> evaluate(Evaluator &evaluator,
4070+
NominalTypeDecl *nominal) const;
4071+
4072+
public:
4073+
bool isCached() const { return true; }
4074+
void diagnoseCycle(DiagnosticEngine &diags) const;
4075+
void noteCycleStep(DiagnosticEngine &diags) const;
4076+
};
4077+
40564078
/// Expand all member attribute macros attached to the given
40574079
/// declaration.
40584080
///

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,9 @@ SWIFT_REQUEST(TypeChecker, ExpandAccessorMacros,
460460
SWIFT_REQUEST(TypeChecker, ExpandConformanceMacros,
461461
ArrayRef<unsigned>(NominalTypeDecl *),
462462
Cached, NoLocationInfo)
463+
SWIFT_REQUEST(TypeChecker, ExpandExtensionMacros,
464+
ArrayRef<unsigned>(NominalTypeDecl *),
465+
Cached, NoLocationInfo)
463466
SWIFT_REQUEST(TypeChecker, ExpandSynthesizedMemberMacroRequest,
464467
ArrayRef<unsigned>(Decl *),
465468
Cached, NoLocationInfo)

include/swift/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ EXPERIMENTAL_FEATURE(StaticAssert, false)
119119
EXPERIMENTAL_FEATURE(NamedOpaqueTypes, false)
120120
EXPERIMENTAL_FEATURE(FlowSensitiveConcurrencyCaptures, false)
121121
EXPERIMENTAL_FEATURE(CodeItemMacros, true)
122+
EXPERIMENTAL_FEATURE(ExtensionMacros, false)
122123
EXPERIMENTAL_FEATURE(TupleConformances, false)
123124
EXPERIMENTAL_FEATURE(InitAccessors, false)
124125

include/swift/Basic/SourceManager.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ class GeneratedSourceInfo {
5454
/// The expansion of an attached conformance macro.
5555
ConformanceMacroExpansion,
5656

57+
/// The expansion of an attached extension macro.
58+
ExtensionMacroExpansion,
59+
5760
/// A new function body that is replacing an existing function body.
5861
ReplacedFunctionBody,
5962

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ NODE(DifferentiableFunctionType)
9393
NODE(ExistentialMetatype)
9494
CONTEXT_NODE(ExplicitClosure)
9595
CONTEXT_NODE(Extension)
96+
NODE(ExtensionAttachedMacroExpansion)
9697
NODE(FieldOffset)
9798
NODE(FreestandingMacroExpansion)
9899
NODE(FullTypeMetadata)

lib/AST/ASTMangler.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3914,7 +3914,8 @@ void ASTMangler::appendMacroExpansionContext(
39143914
case GeneratedSourceInfo::MemberAttributeMacroExpansion:
39153915
case GeneratedSourceInfo::MemberMacroExpansion:
39163916
case GeneratedSourceInfo::PeerMacroExpansion:
3917-
case GeneratedSourceInfo::ConformanceMacroExpansion: {
3917+
case GeneratedSourceInfo::ConformanceMacroExpansion:
3918+
case GeneratedSourceInfo::ExtensionMacroExpansion: {
39183919
auto decl = ASTNode::getFromOpaqueValue(generatedSourceInfo->astNode)
39193920
.get<Decl *>();
39203921
auto attr = generatedSourceInfo->attachedMacroCustomAttr;
@@ -3940,6 +3941,10 @@ void ASTMangler::appendMacroExpansionContext(
39403941
role = MacroRole::Conformance;
39413942
break;
39423943

3944+
case GeneratedSourceInfo::ExtensionMacroExpansion:
3945+
role = MacroRole::Extension;
3946+
break;
3947+
39433948
default:
39443949
llvm_unreachable("Unhandled macro role");
39453950
}
@@ -4004,6 +4009,10 @@ void ASTMangler::appendMacroExpansionOperator(
40044009
case MacroRole::Conformance:
40054010
appendOperator("fMc", Index(discriminator));
40064011
break;
4012+
4013+
case MacroRole::Extension:
4014+
appendOperator("fMe", Index(discriminator));
4015+
break;
40074016
}
40084017
}
40094018

lib/AST/ASTPrinter.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2852,6 +2852,14 @@ static bool usesFeatureCodeItemMacros(Decl *decl) {
28522852
return macro->getMacroRoles().contains(MacroRole::CodeItem);
28532853
}
28542854

2855+
static bool usesFeatureExtensionMacros(Decl *decl) {
2856+
auto macro = dyn_cast<MacroDecl>(decl);
2857+
if (!macro)
2858+
return false;
2859+
2860+
return macro->getMacroRoles().contains(MacroRole::Extension);
2861+
}
2862+
28552863
static bool usesFeatureAttachedMacros(Decl *decl) {
28562864
auto macro = dyn_cast<MacroDecl>(decl);
28572865
if (!macro)

lib/AST/ASTScopeCreation.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ ASTSourceFileScope::ASTSourceFileScope(SourceFile *SF,
272272
case MacroRole::Accessor:
273273
case MacroRole::MemberAttribute:
274274
case MacroRole::Conformance:
275+
case MacroRole::Extension:
275276
parentLoc = expansion.getStartLoc();
276277
break;
277278
case MacroRole::Peer: {

lib/AST/ConformanceLookupTable.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,10 @@ void ConformanceLookupTable::updateLookupTable(NominalTypeDecl *nominal,
286286
ASTContext &ctx = nominal->getASTContext();
287287
(void)evaluateOrDefault(
288288
ctx.evaluator, ExpandConformanceMacros{nominal}, { });
289+
290+
// Expand extension macros.
291+
(void)evaluateOrDefault(
292+
ctx.evaluator, ExpandExtensionMacros{nominal}, { });
289293
},
290294
[&](ExtensionDecl *ext,
291295
ArrayRef<ConformanceConstructionInfo> protos) {

lib/AST/Decl.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10359,7 +10359,7 @@ std::vector<MacroRole> swift::getAllMacroRoles() {
1035910359
return {
1036010360
MacroRole::Expression, MacroRole::Declaration, MacroRole::Accessor,
1036110361
MacroRole::MemberAttribute, MacroRole::Member, MacroRole::Peer,
10362-
MacroRole::Conformance, MacroRole::CodeItem,
10362+
MacroRole::Conformance, MacroRole::CodeItem, MacroRole::Extension,
1036310363
};
1036410364
}
1036510365

@@ -10388,6 +10388,9 @@ StringRef swift::getMacroRoleString(MacroRole role) {
1038810388

1038910389
case MacroRole::CodeItem:
1039010390
return "codeItem";
10391+
10392+
case MacroRole::Extension:
10393+
return "extension";
1039110394
}
1039210395
}
1039310396

@@ -10447,7 +10450,8 @@ static MacroRoles attachedMacroRoles = (MacroRoles() |
1044710450
MacroRole::MemberAttribute |
1044810451
MacroRole::Member |
1044910452
MacroRole::Peer |
10450-
MacroRole::Conformance);
10453+
MacroRole::Conformance |
10454+
MacroRole::Extension);
1045110455

1045210456
bool swift::isFreestandingMacro(MacroRoles contexts) {
1045310457
return bool(contexts & freestandingMacroRoles);
@@ -10477,6 +10481,8 @@ bool swift::isMacroSupported(MacroRole role, ASTContext &ctx) {
1047710481
return true;
1047810482
case MacroRole::CodeItem:
1047910483
return ctx.LangOpts.hasFeature(Feature::CodeItemMacros);
10484+
case MacroRole::Extension:
10485+
return ctx.LangOpts.hasFeature(Feature::ExtensionMacros);
1048010486
}
1048110487
}
1048210488

@@ -10675,6 +10681,7 @@ void MacroDecl::getIntroducedNames(MacroRole role, ValueDecl *attachedTo,
1067510681
case MacroRole::Member:
1067610682
case MacroRole::Peer:
1067710683
case MacroRole::CodeItem:
10684+
case MacroRole::Extension:
1067810685
names.push_back(MacroDecl::getUniqueNamePlaceholder(getASTContext()));
1067910686
break;
1068010687

@@ -10870,6 +10877,7 @@ MacroDiscriminatorContext MacroDiscriminatorContext::getParentOf(
1087010877
case GeneratedSourceInfo::MemberMacroExpansion:
1087110878
case GeneratedSourceInfo::PeerMacroExpansion:
1087210879
case GeneratedSourceInfo::ConformanceMacroExpansion:
10880+
case GeneratedSourceInfo::ExtensionMacroExpansion:
1087310881
case GeneratedSourceInfo::PrettyPrinted:
1087410882
case GeneratedSourceInfo::ReplacedFunctionBody:
1087510883
return origDC;

lib/AST/DiagnosticEngine.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,6 +1288,7 @@ DiagnosticEngine::diagnosticInfoForDiagnostic(const Diagnostic &diagnostic) {
12881288
case GeneratedSourceInfo::MemberMacroExpansion:
12891289
case GeneratedSourceInfo::PeerMacroExpansion:
12901290
case GeneratedSourceInfo::ConformanceMacroExpansion:
1291+
case GeneratedSourceInfo::ExtensionMacroExpansion:
12911292
case GeneratedSourceInfo::PrettyPrinted:
12921293
fixIts = {};
12931294
break;
@@ -1335,7 +1336,8 @@ DiagnosticEngine::getGeneratedSourceBufferNotes(SourceLoc loc) {
13351336
case GeneratedSourceInfo::MemberAttributeMacroExpansion:
13361337
case GeneratedSourceInfo::MemberMacroExpansion:
13371338
case GeneratedSourceInfo::PeerMacroExpansion:
1338-
case GeneratedSourceInfo::ConformanceMacroExpansion: {
1339+
case GeneratedSourceInfo::ConformanceMacroExpansion:
1340+
case GeneratedSourceInfo::ExtensionMacroExpansion: {
13391341
SourceRange origRange = expansionNode.getSourceRange();
13401342
DeclName macroName = getGeneratedSourceInfoMacroName(*generatedInfo);
13411343

@@ -1533,7 +1535,8 @@ swift::getGeneratedSourceInfoMacroName(const GeneratedSourceInfo &info) {
15331535
case GeneratedSourceInfo::MemberAttributeMacroExpansion:
15341536
case GeneratedSourceInfo::MemberMacroExpansion:
15351537
case GeneratedSourceInfo::PeerMacroExpansion:
1536-
case GeneratedSourceInfo::ConformanceMacroExpansion: {
1538+
case GeneratedSourceInfo::ConformanceMacroExpansion:
1539+
case GeneratedSourceInfo::ExtensionMacroExpansion: {
15371540
DeclName macroName;
15381541
if (auto customAttr = info.attachedMacroCustomAttr) {
15391542
// FIXME: How will we handle deserialized custom attributes like this?

lib/AST/Module.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,8 @@ ModuleDecl::getOriginalLocation(SourceLoc loc) const {
848848
case GeneratedSourceInfo::MemberAttributeMacroExpansion:
849849
case GeneratedSourceInfo::MemberMacroExpansion:
850850
case GeneratedSourceInfo::PeerMacroExpansion:
851-
case GeneratedSourceInfo::ConformanceMacroExpansion: {
851+
case GeneratedSourceInfo::ConformanceMacroExpansion:
852+
case GeneratedSourceInfo::ExtensionMacroExpansion: {
852853
// Location was within a macro expansion, return the expansion site, not
853854
// the insertion location.
854855
if (info->attachedMacroCustomAttr) {
@@ -1158,6 +1159,9 @@ llvm::Optional<MacroRole> SourceFile::getFulfilledMacroRole() const {
11581159
case GeneratedSourceInfo::ConformanceMacroExpansion:
11591160
return MacroRole::Conformance;
11601161

1162+
case GeneratedSourceInfo::ExtensionMacroExpansion:
1163+
return MacroRole::Extension;
1164+
11611165
case GeneratedSourceInfo::ReplacedFunctionBody:
11621166
case GeneratedSourceInfo::PrettyPrinted:
11631167
return llvm::None;

lib/AST/NameLookup.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1794,6 +1794,20 @@ populateLookupTableEntryFromMacroExpansions(ASTContext &ctx,
17941794
}
17951795
}
17961796

1797+
// Trigger the expansion of extension macros on the container, if any of the
1798+
// names match.
1799+
{
1800+
MacroIntroducedNameTracker nameTracker;
1801+
auto decl = dyn_cast<NominalTypeDecl>(container.getAsDecl());
1802+
forEachPotentialAttachedMacro(decl, MacroRole::Extension, nameTracker);
1803+
if (decl && nameTracker.shouldExpandForName(name)) {
1804+
(void)evaluateOrDefault(
1805+
ctx.evaluator,
1806+
ExpandExtensionMacros{decl},
1807+
false);
1808+
}
1809+
}
1810+
17971811
auto dc = container.getAsDeclContext();
17981812
auto *module = dc->getParentModule();
17991813
auto idc = container.getAsIterableDeclContext();

lib/AST/TypeCheckRequests.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1873,6 +1873,22 @@ void ExpandConformanceMacros::noteCycleStep(DiagnosticEngine &diags) const {
18731873
decl->getName());
18741874
}
18751875

1876+
void ExpandExtensionMacros::diagnoseCycle(DiagnosticEngine &diags) const {
1877+
auto decl = std::get<0>(getStorage());
1878+
diags.diagnose(decl->getLoc(),
1879+
diag::macro_expand_circular_reference_entity,
1880+
"extension",
1881+
decl->getName());
1882+
}
1883+
1884+
void ExpandExtensionMacros::noteCycleStep(DiagnosticEngine &diags) const {
1885+
auto decl = std::get<0>(getStorage());
1886+
diags.diagnose(decl->getLoc(),
1887+
diag::macro_expand_circular_reference_entity_through,
1888+
"extension",
1889+
decl->getName());
1890+
}
1891+
18761892
void ExpandMemberAttributeMacros::diagnoseCycle(DiagnosticEngine &diags) const {
18771893
auto decl = std::get<0>(getStorage());
18781894
if (auto value = dyn_cast<ValueDecl>(decl)) {

lib/ASTGen/Sources/ASTGen/Macros.swift

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,15 @@ enum MacroPluginKind: UInt8 {
6060
extension MacroRole {
6161
init(rawMacroRole: UInt8) {
6262
switch rawMacroRole {
63-
case 0x01: self = .expression
64-
case 0x02: self = .declaration
65-
case 0x04: self = .accessor
66-
case 0x08: self = .memberAttribute
67-
case 0x10: self = .member
68-
case 0x20: self = .peer
69-
case 0x40: self = .conformance
70-
case 0x80: self = .codeItem
63+
case 0: self = .expression
64+
case 1: self = .declaration
65+
case 2: self = .accessor
66+
case 3: self = .memberAttribute
67+
case 4: self = .member
68+
case 5: self = .peer
69+
case 6: self = .conformance
70+
case 7: self = .codeItem
71+
case 8: self = .`extension`
7172

7273
default: fatalError("unknown macro role")
7374
}
@@ -523,7 +524,7 @@ func expandFreestandingMacroIPC(
523524
// Map the macro role.
524525
let pluginMacroRole: PluginMessage.MacroRole
525526
switch macroRole {
526-
case .accessor, .member, .memberAttribute, .peer, .conformance:
527+
case .accessor, .member, .memberAttribute, .peer, .conformance, .extension:
527528
preconditionFailure("unhandled macro role for freestanding macro")
528529

529530
case .expression: pluginMacroRole = .expression
@@ -812,6 +813,7 @@ func expandAttachedMacroIPC(
812813
case .memberAttribute: macroRole = .memberAttribute
813814
case .peer: macroRole = .peer
814815
case .conformance: macroRole = .conformance
816+
case .extension: macroRole = .`extension`
815817
case
816818
.expression,
817819
.declaration,

lib/ASTGen/Sources/ASTGen/PluginMessages.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ internal enum PluginToHostMessage: Codable {
107107
case peer
108108
case conformance
109109
case codeItem
110+
case `extension`
110111
}
111112

112113
struct SourceLocation: Codable {

lib/Basic/SourceLoc.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ void SourceManager::setGeneratedSourceInfo(
380380
case GeneratedSourceInfo::MemberMacroExpansion:
381381
case GeneratedSourceInfo::PeerMacroExpansion:
382382
case GeneratedSourceInfo::ConformanceMacroExpansion:
383+
case GeneratedSourceInfo::ExtensionMacroExpansion:
383384
case GeneratedSourceInfo::PrettyPrinted:
384385
break;
385386

lib/Demangling/Demangler.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4068,7 +4068,8 @@ static bool isMacroExpansionNodeKind(Node::Kind kind) {
40684068
kind == Node::Kind::FreestandingMacroExpansion ||
40694069
kind == Node::Kind::MemberAttachedMacroExpansion ||
40704070
kind == Node::Kind::PeerAttachedMacroExpansion ||
4071-
kind == Node::Kind::ConformanceAttachedMacroExpansion;
4071+
kind == Node::Kind::ConformanceAttachedMacroExpansion ||
4072+
kind == Node::Kind::ExtensionAttachedMacroExpansion;
40724073
}
40734074

40744075
NodePointer Demangler::demangleMacroExpansion() {
@@ -4112,6 +4113,12 @@ NodePointer Demangler::demangleMacroExpansion() {
41124113
isFreestanding = false;
41134114
break;
41144115

4116+
case 'e':
4117+
kind = Node::Kind::ExtensionAttachedMacroExpansion;
4118+
isAttached = true;
4119+
isFreestanding = false;
4120+
break;
4121+
41154122
case 'u':
41164123
kind = Node::Kind::MacroExpansionUniqueName;
41174124
isAttached = false;

lib/Demangling/NodePrinter.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ class NodePrinter {
387387
case Node::Kind::NoEscapeFunctionType:
388388
case Node::Kind::ExplicitClosure:
389389
case Node::Kind::Extension:
390+
case Node::Kind::ExtensionAttachedMacroExpansion:
390391
case Node::Kind::EnumCase:
391392
case Node::Kind::FieldOffset:
392393
case Node::Kind::FreestandingMacroExpansion:
@@ -1469,6 +1470,12 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth,
14691470
("conformance macro @" + nodeToString(Node->getChild(2)) +
14701471
" expansion #"),
14711472
(int)Node->getChild(3)->getIndex() + 1);
1473+
case Node::Kind::ExtensionAttachedMacroExpansion:
1474+
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
1475+
/*hasName*/true,
1476+
("extension macro @" + nodeToString(Node->getChild(2)) +
1477+
" expansion #"),
1478+
(int)Node->getChild(3)->getIndex() + 1);
14721479
case Node::Kind::MacroExpansionUniqueName:
14731480
return printEntity(Node, depth, asPrefixContext, TypePrinting::NoType,
14741481
/*hasName*/true, "unique name #",

0 commit comments

Comments
 (0)