Skip to content

Commit 296ebb5

Browse files
ApolloZhurxwei
andcommitted
[Macros] Support module-qualified attached macro lookup
Allow attached macro expansion syntax to have a module qualifier, `@Foo.Bar`. rdar: //108621205 Co-Authored-By: Richard Wei <[email protected]>
1 parent 5b23b23 commit 296ebb5

File tree

11 files changed

+201
-68
lines changed

11 files changed

+201
-68
lines changed

include/swift/AST/FreestandingMacroExpansion.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ class ArgumentList;
3434
/// declaration/expression nodes.
3535
struct MacroExpansionInfo : ASTAllocated<MacroExpansionInfo> {
3636
SourceLoc SigilLoc;
37+
DeclNameRef ModuleName;
38+
DeclNameLoc ModuleNameLoc;
3739
DeclNameRef MacroName;
3840
DeclNameLoc MacroNameLoc;
3941
SourceLoc LeftAngleLoc, RightAngleLoc;
@@ -43,13 +45,16 @@ struct MacroExpansionInfo : ASTAllocated<MacroExpansionInfo> {
4345
/// The referenced macro.
4446
ConcreteDeclRef macroRef;
4547

46-
MacroExpansionInfo(SourceLoc sigilLoc, DeclNameRef macroName,
48+
MacroExpansionInfo(SourceLoc sigilLoc, DeclNameRef moduleName,
49+
DeclNameLoc moduleNameLoc, DeclNameRef macroName,
4750
DeclNameLoc macroNameLoc, SourceLoc leftAngleLoc,
4851
SourceLoc rightAngleLoc, ArrayRef<TypeRepr *> genericArgs,
4952
ArgumentList *argList)
50-
: SigilLoc(sigilLoc), MacroName(macroName), MacroNameLoc(macroNameLoc),
51-
LeftAngleLoc(leftAngleLoc), RightAngleLoc(rightAngleLoc),
52-
GenericArgs(genericArgs), ArgList(argList) {}
53+
: SigilLoc(sigilLoc), ModuleName(moduleName),
54+
ModuleNameLoc(moduleNameLoc), MacroName(macroName),
55+
MacroNameLoc(macroNameLoc), LeftAngleLoc(leftAngleLoc),
56+
RightAngleLoc(rightAngleLoc), GenericArgs(genericArgs),
57+
ArgList(argList) {}
5358

5459
SourceLoc getLoc() const { return SigilLoc; }
5560
SourceRange getGenericArgsRange() const {
@@ -85,6 +90,10 @@ class FreestandingMacroExpansion {
8590

8691
SourceLoc getPoundLoc() const { return getExpansionInfo()->SigilLoc; }
8792

93+
DeclNameLoc getModuleNameLoc() const {
94+
return getExpansionInfo()->ModuleNameLoc;
95+
}
96+
DeclNameRef getModuleName() const { return getExpansionInfo()->ModuleName; }
8897
DeclNameLoc getMacroNameLoc() const {
8998
return getExpansionInfo()->MacroNameLoc;
9099
}

include/swift/AST/NameLookup.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -550,8 +550,10 @@ void filterForDiscriminator(SmallVectorImpl<Result> &results,
550550

551551
/// \returns The set of macro declarations with the given name that
552552
/// fulfill any of the given macro roles.
553-
SmallVector<MacroDecl *, 1>
554-
lookupMacros(DeclContext *dc, DeclNameRef macroName, MacroRoles roles);
553+
SmallVector<MacroDecl *, 1> lookupMacros(DeclContext *dc,
554+
DeclNameRef moduleName,
555+
DeclNameRef macroName,
556+
MacroRoles roles);
555557

556558
/// \returns Whether the given source location is inside an attached
557559
/// or freestanding macro argument.

include/swift/AST/TypeCheckRequests.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3415,6 +3415,8 @@ class UnresolvedMacroReference {
34153415
}
34163416

34173417
SourceLoc getSigilLoc() const;
3418+
DeclNameRef getModuleName() const;
3419+
DeclNameLoc getModuleNameLoc() const;
34183420
DeclNameRef getMacroName() const;
34193421
DeclNameLoc getMacroNameLoc() const;
34203422
SourceRange getGenericArgsRange() const;

lib/AST/Decl.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11320,11 +11320,16 @@ MacroExpansionDecl::create(
1132011320
ArgumentList *args
1132111321
) {
1132211322
ASTContext &ctx = dc->getASTContext();
11323-
MacroExpansionInfo *info = new (ctx) MacroExpansionInfo{
11324-
poundLoc, macro, macroLoc,
11325-
leftAngleLoc, rightAngleLoc, genericArgs,
11326-
args ? args : ArgumentList::createImplicit(ctx, {})
11327-
};
11323+
MacroExpansionInfo *info = new (ctx)
11324+
MacroExpansionInfo{poundLoc,
11325+
/*moduleName*/ DeclNameRef(),
11326+
/*moduleNameLoc*/ DeclNameLoc(),
11327+
macro,
11328+
macroLoc,
11329+
leftAngleLoc,
11330+
rightAngleLoc,
11331+
genericArgs,
11332+
args ? args : ArgumentList::createImplicit(ctx, {})};
1132811333
return new (ctx) MacroExpansionDecl(dc, info);
1132911334
}
1133011335

lib/AST/Expr.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2739,10 +2739,15 @@ MacroExpansionExpr *MacroExpansionExpr::create(
27392739
) {
27402740
ASTContext &ctx = dc->getASTContext();
27412741
MacroExpansionInfo *info = new (ctx) MacroExpansionInfo{
2742-
sigilLoc, macroName, macroNameLoc,
2743-
leftAngleLoc, rightAngleLoc, genericArgs,
2744-
argList ? argList : ArgumentList::createImplicit(ctx, {})
2745-
};
2742+
sigilLoc,
2743+
/*moduleName*/ DeclNameRef(),
2744+
/*moduleNameLoc*/ DeclNameLoc(),
2745+
macroName,
2746+
macroNameLoc,
2747+
leftAngleLoc,
2748+
rightAngleLoc,
2749+
genericArgs,
2750+
argList ? argList : ArgumentList::createImplicit(ctx, {})};
27462751
return new (ctx) MacroExpansionExpr(dc, info, roles, isImplicit, ty);
27472752
}
27482753

lib/AST/NameLookup.cpp

Lines changed: 69 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1621,9 +1621,10 @@ static DeclName adjustLazyMacroExpansionNameKey(
16211621
return name;
16221622
}
16231623

1624-
SmallVector<MacroDecl *, 1>
1625-
namelookup::lookupMacros(DeclContext *dc, DeclNameRef macroName,
1626-
MacroRoles roles) {
1624+
SmallVector<MacroDecl *, 1> namelookup::lookupMacros(DeclContext *dc,
1625+
DeclNameRef moduleName,
1626+
DeclNameRef macroName,
1627+
MacroRoles roles) {
16271628
SmallVector<MacroDecl *, 1> choices;
16281629
auto moduleScopeDC = dc->getModuleScopeContext();
16291630
ASTContext &ctx = moduleScopeDC->getASTContext();
@@ -1633,29 +1634,52 @@ namelookup::lookupMacros(DeclContext *dc, DeclNameRef macroName,
16331634
bool onlyMacros = static_cast<bool>(roles & getFreestandingMacroRoles()) &&
16341635
!(roles - getFreestandingMacroRoles());
16351636

1636-
// Macro lookup should always exclude macro expansions; macro
1637-
// expansions cannot introduce new macro declarations. Note that
1638-
// the source location here doesn't matter.
1639-
UnqualifiedLookupDescriptor descriptor{
1640-
macroName, moduleScopeDC, SourceLoc(),
1641-
UnqualifiedLookupFlags::ExcludeMacroExpansions
1642-
};
1643-
1644-
if (onlyMacros)
1645-
descriptor.Options |= UnqualifiedLookupFlags::MacroLookup;
1646-
1647-
auto lookup = evaluateOrDefault(
1648-
ctx.evaluator, UnqualifiedLookupRequest{descriptor}, {});
1649-
1650-
for (const auto &found : lookup.allResults()) {
1651-
if (auto macro = dyn_cast<MacroDecl>(found.getValueDecl())) {
1637+
auto addChoiceIfApplicable = [&](ValueDecl *decl) {
1638+
if (auto macro = dyn_cast<MacroDecl>(decl)) {
16521639
auto candidateRoles = macro->getMacroRoles();
16531640
if ((candidateRoles && roles.contains(candidateRoles)) ||
16541641
// FIXME: `externalMacro` should have all roles.
16551642
macro->getBaseIdentifier().str() == "externalMacro") {
16561643
choices.push_back(macro);
16571644
}
16581645
}
1646+
};
1647+
1648+
// When a module is specified, it's a module-qualified lookup.
1649+
if (moduleName) {
1650+
UnqualifiedLookupDescriptor moduleLookupDesc(
1651+
moduleName, moduleScopeDC, SourceLoc(),
1652+
UnqualifiedLookupFlags::TypeLookup);
1653+
auto moduleLookup = evaluateOrDefault(
1654+
ctx.evaluator, UnqualifiedLookupRequest{moduleLookupDesc}, {});
1655+
auto foundTypeDecl = moduleLookup.getSingleTypeResult();
1656+
auto *moduleDecl = dyn_cast_or_null<ModuleDecl>(foundTypeDecl);
1657+
if (!moduleDecl)
1658+
return {};
1659+
1660+
ModuleQualifiedLookupRequest req{moduleScopeDC, moduleDecl, macroName,
1661+
SourceLoc(), NL_ExcludeMacroExpansions};
1662+
auto lookup = evaluateOrDefault(ctx.evaluator, req, {});
1663+
for (auto *found : lookup)
1664+
addChoiceIfApplicable(found);
1665+
}
1666+
// Otherwise it's an unqualified lookup.
1667+
else {
1668+
// Macro lookup should always exclude macro expansions; macro
1669+
// expansions cannot introduce new macro declarations. Note that
1670+
// the source location here doesn't matter.
1671+
UnqualifiedLookupDescriptor descriptor{
1672+
macroName, moduleScopeDC, SourceLoc(),
1673+
UnqualifiedLookupFlags::ExcludeMacroExpansions};
1674+
1675+
if (onlyMacros)
1676+
descriptor.Options |= UnqualifiedLookupFlags::MacroLookup;
1677+
1678+
auto lookup = evaluateOrDefault(ctx.evaluator,
1679+
UnqualifiedLookupRequest{descriptor}, {});
1680+
1681+
for (const auto &found : lookup.allResults())
1682+
addChoiceIfApplicable(found.getValueDecl());
16591683
}
16601684

16611685
return choices;
@@ -1674,8 +1698,9 @@ namelookup::isInMacroArgument(SourceFile *sourceFile, SourceLoc loc) {
16741698
inMacroArgument = true;
16751699
} else if (auto *attr = macro.getAttr()) {
16761700
auto *moduleScope = sourceFile->getModuleScopeContext();
1677-
auto results = lookupMacros(moduleScope, macro.getMacroName(),
1678-
getAttachedMacroRoles());
1701+
auto results =
1702+
lookupMacros(moduleScope, macro.getModuleName(),
1703+
macro.getMacroName(), getAttachedMacroRoles());
16791704
inMacroArgument = !results.empty();
16801705
}
16811706

@@ -3562,10 +3587,29 @@ CustomAttrNominalRequest::evaluate(Evaluator &evaluator,
35623587
// Look for names at module scope, so we don't trigger name lookup for
35633588
// nested scopes. At this point, we're looking to see whether there are
35643589
// any suitable macros.
3565-
if (auto *identTypeRepr =
3566-
dyn_cast_or_null<IdentTypeRepr>(attr->getTypeRepr())) {
3567-
auto macros = namelookup::lookupMacros(
3568-
dc, identTypeRepr->getNameRef(), getAttachedMacroRoles());
3590+
3591+
// Handle a module-qualified name.
3592+
if (auto *memTypeRepr =
3593+
dyn_cast_or_null<MemberTypeRepr>(attr->getTypeRepr())) {
3594+
auto baseTypeRepr = memTypeRepr->getBaseComponent();
3595+
auto memberReprs = memTypeRepr->getMemberComponents();
3596+
auto *moduleNameRepr = dyn_cast<IdentTypeRepr>(baseTypeRepr);
3597+
3598+
if (moduleNameRepr && (memberReprs.size() == 1)) {
3599+
if (auto *macroNameRepr = dyn_cast<IdentTypeRepr>(memberReprs.front())) {
3600+
auto moduleName = moduleNameRepr->getNameRef();
3601+
auto macroName = macroNameRepr->getNameRef();
3602+
auto macros = namelookup::lookupMacros(dc, moduleName, macroName,
3603+
getAttachedMacroRoles());
3604+
if (!macros.empty())
3605+
return nullptr;
3606+
}
3607+
}
3608+
} else if (auto *identTypeRepr =
3609+
dyn_cast_or_null<IdentTypeRepr>(attr->getTypeRepr())) {
3610+
auto macros =
3611+
namelookup::lookupMacros(dc, DeclNameRef(), identTypeRepr->getNameRef(),
3612+
getAttachedMacroRoles());
35693613
if (!macros.empty())
35703614
return nullptr;
35713615
}

lib/AST/TypeCheckRequests.cpp

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1788,14 +1788,35 @@ void swift::simple_display(
17881788
// ResolveMacroRequest computation.
17891789
//----------------------------------------------------------------------------//
17901790

1791+
/// Destructure a type repr for a macro reference.
1792+
///
1793+
/// For a 1-level member type repr whose base and member are both identifier
1794+
/// types, e.g. `Foo.Bar`, return a pair of the base and the member.
1795+
///
1796+
/// For an identifier type repr, return a pair of `nullptr` and the identifier.
1797+
static std::pair<IdentTypeRepr *, IdentTypeRepr *>
1798+
destructureMacroRefTypeRepr(TypeRepr *typeRepr) {
1799+
if (!typeRepr)
1800+
return {nullptr, nullptr};
1801+
if (auto *identType = dyn_cast<IdentTypeRepr>(typeRepr))
1802+
return {nullptr, identType};
1803+
if (auto *memType = dyn_cast<MemberTypeRepr>(typeRepr))
1804+
if (auto *base = dyn_cast<IdentTypeRepr>(memType->getBaseComponent()))
1805+
if (memType->getMemberComponents().size() == 1)
1806+
if (auto first =
1807+
dyn_cast<IdentTypeRepr>(memType->getMemberComponents().front()))
1808+
return {base, first};
1809+
return {nullptr, nullptr};
1810+
}
1811+
17911812
DeclNameRef UnresolvedMacroReference::getMacroName() const {
17921813
if (auto *expansion = pointer.dyn_cast<FreestandingMacroExpansion *>())
17931814
return expansion->getMacroName();
17941815
if (auto *attr = pointer.dyn_cast<CustomAttr *>()) {
1795-
auto *identTypeRepr = dyn_cast_or_null<IdentTypeRepr>(attr->getTypeRepr());
1796-
if (!identTypeRepr)
1816+
auto [_, member] = destructureMacroRefTypeRepr(attr->getTypeRepr());
1817+
if (!member)
17971818
return DeclNameRef();
1798-
return identTypeRepr->getNameRef();
1819+
return member->getNameRef();
17991820
}
18001821
llvm_unreachable("Unhandled case");
18011822
}
@@ -1808,14 +1829,38 @@ SourceLoc UnresolvedMacroReference::getSigilLoc() const {
18081829
llvm_unreachable("Unhandled case");
18091830
}
18101831

1832+
DeclNameRef UnresolvedMacroReference::getModuleName() const {
1833+
if (auto *expansion = pointer.dyn_cast<FreestandingMacroExpansion *>())
1834+
return expansion->getModuleName();
1835+
if (auto *attr = pointer.dyn_cast<CustomAttr *>()) {
1836+
auto [base, _] = destructureMacroRefTypeRepr(attr->getTypeRepr());
1837+
if (!base)
1838+
return DeclNameRef();
1839+
return base->getNameRef();
1840+
}
1841+
llvm_unreachable("Unhandled case");
1842+
}
1843+
1844+
DeclNameLoc UnresolvedMacroReference::getModuleNameLoc() const {
1845+
if (auto *expansion = pointer.dyn_cast<FreestandingMacroExpansion *>())
1846+
return expansion->getModuleNameLoc();
1847+
if (auto *attr = pointer.dyn_cast<CustomAttr *>()) {
1848+
auto [base, _] = destructureMacroRefTypeRepr(attr->getTypeRepr());
1849+
if (!base)
1850+
return DeclNameLoc();
1851+
return base->getNameLoc();
1852+
}
1853+
llvm_unreachable("Unhandled case");
1854+
}
1855+
18111856
DeclNameLoc UnresolvedMacroReference::getMacroNameLoc() const {
18121857
if (auto *expansion = pointer.dyn_cast<FreestandingMacroExpansion *>())
18131858
return expansion->getMacroNameLoc();
18141859
if (auto *attr = pointer.dyn_cast<CustomAttr *>()) {
1815-
auto *identTypeRepr = dyn_cast_or_null<IdentTypeRepr>(attr->getTypeRepr());
1816-
if (!identTypeRepr)
1860+
auto [_, member] = destructureMacroRefTypeRepr(attr->getTypeRepr());
1861+
if (!member)
18171862
return DeclNameLoc();
1818-
return identTypeRepr->getNameLoc();
1863+
return member->getNameLoc();
18191864
}
18201865
llvm_unreachable("Unhandled case");
18211866
}
@@ -1825,8 +1870,10 @@ SourceRange UnresolvedMacroReference::getGenericArgsRange() const {
18251870
return expansion->getGenericArgsRange();
18261871

18271872
if (auto *attr = pointer.dyn_cast<CustomAttr *>()) {
1828-
auto *typeRepr = attr->getTypeRepr();
1829-
auto *genericTypeRepr = dyn_cast_or_null<GenericIdentTypeRepr>(typeRepr);
1873+
auto [_, member] = destructureMacroRefTypeRepr(attr->getTypeRepr());
1874+
if (!member)
1875+
return SourceRange();
1876+
auto *genericTypeRepr = dyn_cast_or_null<GenericIdentTypeRepr>(member);
18301877
if (!genericTypeRepr)
18311878
return SourceRange();
18321879

@@ -1841,8 +1888,10 @@ ArrayRef<TypeRepr *> UnresolvedMacroReference::getGenericArgs() const {
18411888
return expansion->getGenericArgs();
18421889

18431890
if (auto *attr = pointer.dyn_cast<CustomAttr *>()) {
1844-
auto *typeRepr = attr->getTypeRepr();
1845-
auto *genericTypeRepr = dyn_cast_or_null<GenericIdentTypeRepr>(typeRepr);
1891+
auto [_, member] = destructureMacroRefTypeRepr(attr->getTypeRepr());
1892+
if (!member)
1893+
return {};
1894+
auto *genericTypeRepr = dyn_cast_or_null<GenericIdentTypeRepr>(member);
18461895
if (!genericTypeRepr)
18471896
return {};
18481897

lib/Sema/CSGen.cpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1367,9 +1367,9 @@ namespace {
13671367
return Type();
13681368

13691369
auto macroIdent = ctx.getIdentifier(kind);
1370-
auto macros = lookupMacros(
1371-
macroIdent, FunctionRefKind::Unapplied,
1372-
MacroRole::Expression);
1370+
auto macros =
1371+
lookupMacros(Identifier(), macroIdent, FunctionRefKind::Unapplied,
1372+
MacroRole::Expression);
13731373
if (!macros.empty()) {
13741374
// Introduce an overload set for the macro reference.
13751375
auto locator = CS.getConstraintLocator(expr);
@@ -3970,13 +3970,13 @@ namespace {
39703970
}
39713971

39723972
/// Lookup all macros with the given macro name.
3973-
SmallVector<OverloadChoice, 1>
3974-
lookupMacros(Identifier macroName,
3975-
FunctionRefKind functionRefKind,
3976-
MacroRoles roles) {
3973+
SmallVector<OverloadChoice, 1> lookupMacros(Identifier moduleName,
3974+
Identifier macroName,
3975+
FunctionRefKind functionRefKind,
3976+
MacroRoles roles) {
39773977
SmallVector<OverloadChoice, 1> choices;
3978-
auto results = namelookup::lookupMacros(
3979-
CurDC, DeclNameRef(macroName), roles);
3978+
auto results = namelookup::lookupMacros(CurDC, DeclNameRef(moduleName),
3979+
DeclNameRef(macroName), roles);
39803980
for (const auto &result : results) {
39813981
OverloadChoice choice = OverloadChoice(Type(), result, functionRefKind);
39823982
choices.push_back(choice);
@@ -3998,10 +3998,11 @@ namespace {
39983998
CS.associateArgumentList(locator, expr->getArgs());
39993999

40004000
// Look up the macros with this name.
4001+
auto moduleIdent = expr->getModuleName().getBaseIdentifier();
40014002
auto macroIdent = expr->getMacroName().getBaseIdentifier();
40024003
FunctionRefKind functionRefKind = FunctionRefKind::SingleApply;
4003-
auto macros = lookupMacros(
4004-
macroIdent, functionRefKind, expr->getMacroRoles());
4004+
auto macros = lookupMacros(moduleIdent, macroIdent, functionRefKind,
4005+
expr->getMacroRoles());
40054006
if (macros.empty()) {
40064007
ctx.Diags.diagnose(expr->getMacroNameLoc(), diag::macro_undefined,
40074008
macroIdent)

lib/Sema/TypeCheckMacros.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1868,8 +1868,8 @@ ConcreteDeclRef ResolveMacroRequest::evaluate(Evaluator &evaluator,
18681868
// When a macro is not found for a custom attribute, it may be a non-macro.
18691869
// So bail out to prevent diagnostics from the contraint system.
18701870
if (macroRef.getAttr()) {
1871-
auto foundMacros = namelookup::lookupMacros(
1872-
dc, macroRef.getMacroName(), roles);
1871+
auto foundMacros = namelookup::lookupMacros(dc, macroRef.getModuleName(),
1872+
macroRef.getMacroName(), roles);
18731873
if (foundMacros.empty())
18741874
return ConcreteDeclRef();
18751875
}

0 commit comments

Comments
 (0)