Skip to content

Commit 7a46466

Browse files
authored
Merge pull request #66967 from hborla/extension-macro
[Macros] Generalize `conformance` macros as `extension` macros
2 parents d427696 + 7e85ebd commit 7a46466

Some content is hidden

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

53 files changed

+651
-59
lines changed

include/swift/AST/Attr.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2397,36 +2397,45 @@ class ObjCImplementationAttr final : public DeclAttribute {
23972397
/// which declares one of the roles that a given macro can inhabit.
23982398
class MacroRoleAttr final
23992399
: public DeclAttribute,
2400-
private llvm::TrailingObjects<MacroRoleAttr, MacroIntroducedDeclName> {
2400+
private llvm::TrailingObjects<MacroRoleAttr, MacroIntroducedDeclName,
2401+
TypeExpr *> {
24012402
friend TrailingObjects;
24022403

24032404
MacroSyntax syntax;
24042405
MacroRole role;
24052406
unsigned numNames;
2407+
unsigned numConformances;
24062408
SourceLoc lParenLoc, rParenLoc;
24072409

24082410
MacroRoleAttr(SourceLoc atLoc, SourceRange range, MacroSyntax syntax,
24092411
SourceLoc lParenLoc, MacroRole role,
24102412
ArrayRef<MacroIntroducedDeclName> names,
2413+
ArrayRef<TypeExpr *> conformances,
24112414
SourceLoc rParenLoc, bool implicit);
24122415

24132416
public:
24142417
static MacroRoleAttr *create(ASTContext &ctx, SourceLoc atLoc,
24152418
SourceRange range, MacroSyntax syntax,
24162419
SourceLoc lParenLoc, MacroRole role,
24172420
ArrayRef<MacroIntroducedDeclName> names,
2421+
ArrayRef<TypeExpr *> conformances,
24182422
SourceLoc rParenLoc, bool implicit);
24192423

24202424
size_t numTrailingObjects(OverloadToken<MacroIntroducedDeclName>) const {
24212425
return numNames;
24222426
}
24232427

2428+
size_t numTrailingObjects(OverloadToken<TypeExpr *>) const {
2429+
return numConformances;
2430+
}
2431+
24242432
SourceLoc getLParenLoc() const { return lParenLoc; }
24252433
SourceLoc getRParenLoc() const { return rParenLoc; }
24262434

24272435
MacroSyntax getMacroSyntax() const { return syntax; }
24282436
MacroRole getMacroRole() const { return role; }
24292437
ArrayRef<MacroIntroducedDeclName> getNames() const;
2438+
ArrayRef<TypeExpr *> getConformances() const;
24302439
bool hasNameKind(MacroIntroducedDeclNameKind kind) const;
24312440

24322441
static bool classof(const DeclAttribute *DA) {

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7263,6 +7263,9 @@ ERROR(global_arbitrary_name,none,
72637263
"'%0' macros are not allowed to introduce arbitrary names "
72647264
"at global scope",
72657265
(StringRef))
7266+
ERROR(local_extension_macro,none,
7267+
"local type cannot have attached extension macro",
7268+
())
72667269

72677270
ERROR(macro_resolve_circular_reference, none,
72687271
"circular reference resolving %select{freestanding|attached}0 macro %1",

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/PrintOptions.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,11 @@ struct PrintOptions {
578578
/// If false, we print them as ordinary associated types.
579579
bool PrintPrimaryAssociatedTypes = true;
580580

581+
/// Whether or not to print \c @attached(extension) attributes on
582+
/// macro declarations. This is used for feature suppression in
583+
/// Swift interface printing.
584+
bool PrintExtensionMacroAttributes = true;
585+
581586
/// If this is not \c nullptr then function bodies (including accessors
582587
/// and constructors) will be printed by this function.
583588
std::function<void(const ValueDecl *, ASTPrinter &)> FunctionBody;

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: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ EXPERIMENTAL_FEATURE(CodeItemMacros, true)
123123
EXPERIMENTAL_FEATURE(TupleConformances, false)
124124
EXPERIMENTAL_FEATURE(InitAccessors, false)
125125

126+
EXPERIMENTAL_FEATURE(ExtensionMacros, false)
127+
SUPPRESSIBLE_LANGUAGE_FEATURE(ExtensionMacroAttr, 0, "@attached(extension)", true)
128+
126129
// Whether to enable @_used and @_section attributes
127130
EXPERIMENTAL_FEATURE(SymbolLinkageMarkers, true)
128131

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: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2852,6 +2852,26 @@ 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+
2863+
static bool usesFeatureExtensionMacroAttr(Decl *decl) {
2864+
return usesFeatureExtensionMacros(decl);
2865+
}
2866+
2867+
static void suppressingFeatureExtensionMacroAttr(PrintOptions &options,
2868+
llvm::function_ref<void()> action) {
2869+
bool originalPrintExtensionMacroAttrs = options.PrintExtensionMacroAttributes;
2870+
options.PrintExtensionMacroAttributes = false;
2871+
action();
2872+
options.PrintExtensionMacroAttributes = originalPrintExtensionMacroAttrs;
2873+
}
2874+
28552875
static bool usesFeatureAttachedMacros(Decl *decl) {
28562876
auto macro = dyn_cast<MacroDecl>(decl);
28572877
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/Attr.cpp

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,6 +1371,13 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
13711371

13721372
case DAK_MacroRole: {
13731373
auto Attr = cast<MacroRoleAttr>(this);
1374+
1375+
// Suppress @attached(extension) if needed.
1376+
if (!Options.PrintExtensionMacroAttributes &&
1377+
Attr->getMacroRole() == MacroRole::Extension) {
1378+
break;
1379+
}
1380+
13741381
switch (Attr->getMacroSyntax()) {
13751382
case MacroSyntax::Freestanding:
13761383
Printer.printAttrName("@freestanding");
@@ -2491,23 +2498,32 @@ MacroRoleAttr::MacroRoleAttr(SourceLoc atLoc, SourceRange range,
24912498
MacroSyntax syntax, SourceLoc lParenLoc,
24922499
MacroRole role,
24932500
ArrayRef<MacroIntroducedDeclName> names,
2501+
ArrayRef<TypeExpr *> conformances,
24942502
SourceLoc rParenLoc, bool implicit)
24952503
: DeclAttribute(DAK_MacroRole, atLoc, range, implicit),
2496-
syntax(syntax), role(role), numNames(names.size()), lParenLoc(lParenLoc),
2504+
syntax(syntax), role(role), numNames(names.size()),
2505+
numConformances(conformances.size()), lParenLoc(lParenLoc),
24972506
rParenLoc(rParenLoc) {
24982507
auto *trailingNamesBuffer = getTrailingObjects<MacroIntroducedDeclName>();
24992508
std::uninitialized_copy(names.begin(), names.end(), trailingNamesBuffer);
2509+
2510+
auto *trailingConformancesBuffer = getTrailingObjects<TypeExpr *>();
2511+
std::uninitialized_copy(conformances.begin(), conformances.end(),
2512+
trailingConformancesBuffer);
25002513
}
25012514

25022515
MacroRoleAttr *
25032516
MacroRoleAttr::create(ASTContext &ctx, SourceLoc atLoc, SourceRange range,
25042517
MacroSyntax syntax, SourceLoc lParenLoc, MacroRole role,
25052518
ArrayRef<MacroIntroducedDeclName> names,
2519+
ArrayRef<TypeExpr *> conformances,
25062520
SourceLoc rParenLoc, bool implicit) {
2507-
unsigned size = totalSizeToAlloc<MacroIntroducedDeclName>(names.size());
2521+
unsigned size =
2522+
totalSizeToAlloc<MacroIntroducedDeclName, TypeExpr *>(
2523+
names.size(), conformances.size());
25082524
auto *mem = ctx.Allocate(size, alignof(MacroRoleAttr));
25092525
return new (mem) MacroRoleAttr(atLoc, range, syntax, lParenLoc, role, names,
2510-
rParenLoc, implicit);
2526+
conformances, rParenLoc, implicit);
25112527
}
25122528

25132529
ArrayRef<MacroIntroducedDeclName> MacroRoleAttr::getNames() const {
@@ -2517,6 +2533,13 @@ ArrayRef<MacroIntroducedDeclName> MacroRoleAttr::getNames() const {
25172533
};
25182534
}
25192535

2536+
ArrayRef<TypeExpr *> MacroRoleAttr::getConformances() const {
2537+
return {
2538+
getTrailingObjects<TypeExpr *>(),
2539+
numConformances
2540+
};
2541+
}
2542+
25202543
bool MacroRoleAttr::hasNameKind(MacroIntroducedDeclNameKind kind) const {
25212544
return llvm::find_if(getNames(), [kind](MacroIntroducedDeclName name) {
25222545
return name.getKind() == kind;

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
@@ -10362,7 +10362,7 @@ std::vector<MacroRole> swift::getAllMacroRoles() {
1036210362
return {
1036310363
MacroRole::Expression, MacroRole::Declaration, MacroRole::Accessor,
1036410364
MacroRole::MemberAttribute, MacroRole::Member, MacroRole::Peer,
10365-
MacroRole::Conformance, MacroRole::CodeItem,
10365+
MacroRole::Conformance, MacroRole::CodeItem, MacroRole::Extension,
1036610366
};
1036710367
}
1036810368

@@ -10391,6 +10391,9 @@ StringRef swift::getMacroRoleString(MacroRole role) {
1039110391

1039210392
case MacroRole::CodeItem:
1039310393
return "codeItem";
10394+
10395+
case MacroRole::Extension:
10396+
return "extension";
1039410397
}
1039510398
}
1039610399

@@ -10450,7 +10453,8 @@ static MacroRoles attachedMacroRoles = (MacroRoles() |
1045010453
MacroRole::MemberAttribute |
1045110454
MacroRole::Member |
1045210455
MacroRole::Peer |
10453-
MacroRole::Conformance);
10456+
MacroRole::Conformance |
10457+
MacroRole::Extension);
1045410458

1045510459
bool swift::isFreestandingMacro(MacroRoles contexts) {
1045610460
return bool(contexts & freestandingMacroRoles);
@@ -10480,6 +10484,8 @@ bool swift::isMacroSupported(MacroRole role, ASTContext &ctx) {
1048010484
return true;
1048110485
case MacroRole::CodeItem:
1048210486
return ctx.LangOpts.hasFeature(Feature::CodeItemMacros);
10487+
case MacroRole::Extension:
10488+
return ctx.LangOpts.hasFeature(Feature::ExtensionMacros);
1048310489
}
1048410490
}
1048510491

@@ -10678,6 +10684,7 @@ void MacroDecl::getIntroducedNames(MacroRole role, ValueDecl *attachedTo,
1067810684
case MacroRole::Member:
1067910685
case MacroRole::Peer:
1068010686
case MacroRole::CodeItem:
10687+
case MacroRole::Extension:
1068110688
names.push_back(MacroDecl::getUniqueNamePlaceholder(getASTContext()));
1068210689
break;
1068310690

@@ -10873,6 +10880,7 @@ MacroDiscriminatorContext MacroDiscriminatorContext::getParentOf(
1087310880
case GeneratedSourceInfo::MemberMacroExpansion:
1087410881
case GeneratedSourceInfo::PeerMacroExpansion:
1087510882
case GeneratedSourceInfo::ConformanceMacroExpansion:
10883+
case GeneratedSourceInfo::ExtensionMacroExpansion:
1087610884
case GeneratedSourceInfo::PrettyPrinted:
1087710885
case GeneratedSourceInfo::ReplacedFunctionBody:
1087810886
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;

0 commit comments

Comments
 (0)