Skip to content

Commit cca2f12

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 7a920cd commit cca2f12

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
@@ -3418,6 +3418,8 @@ class UnresolvedMacroReference {
34183418
}
34193419

34203420
SourceLoc getSigilLoc() const;
3421+
DeclNameRef getModuleName() const;
3422+
DeclNameLoc getModuleNameLoc() const;
34213423
DeclNameRef getMacroName() const;
34223424
DeclNameLoc getMacroNameLoc() const;
34233425
SourceRange getGenericArgsRange() const;

lib/AST/Decl.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11378,11 +11378,16 @@ MacroExpansionDecl::create(
1137811378
ArgumentList *args
1137911379
) {
1138011380
ASTContext &ctx = dc->getASTContext();
11381-
MacroExpansionInfo *info = new (ctx) MacroExpansionInfo{
11382-
poundLoc, macro, macroLoc,
11383-
leftAngleLoc, rightAngleLoc, genericArgs,
11384-
args ? args : ArgumentList::createImplicit(ctx, {})
11385-
};
11381+
MacroExpansionInfo *info = new (ctx)
11382+
MacroExpansionInfo{poundLoc,
11383+
/*moduleName*/ DeclNameRef(),
11384+
/*moduleNameLoc*/ DeclNameLoc(),
11385+
macro,
11386+
macroLoc,
11387+
leftAngleLoc,
11388+
rightAngleLoc,
11389+
genericArgs,
11390+
args ? args : ArgumentList::createImplicit(ctx, {})};
1138611391
return new (ctx) MacroExpansionDecl(dc, info);
1138711392
}
1138811393

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
@@ -1792,14 +1792,35 @@ void swift::simple_display(
17921792
// ResolveMacroRequest computation.
17931793
//----------------------------------------------------------------------------//
17941794

1795+
/// Destructure a type repr for a macro reference.
1796+
///
1797+
/// For a 1-level member type repr whose base and member are both identifier
1798+
/// types, e.g. `Foo.Bar`, return a pair of the base and the member.
1799+
///
1800+
/// For an identifier type repr, return a pair of `nullptr` and the identifier.
1801+
static std::pair<IdentTypeRepr *, IdentTypeRepr *>
1802+
destructureMacroRefTypeRepr(TypeRepr *typeRepr) {
1803+
if (!typeRepr)
1804+
return {nullptr, nullptr};
1805+
if (auto *identType = dyn_cast<IdentTypeRepr>(typeRepr))
1806+
return {nullptr, identType};
1807+
if (auto *memType = dyn_cast<MemberTypeRepr>(typeRepr))
1808+
if (auto *base = dyn_cast<IdentTypeRepr>(memType->getBaseComponent()))
1809+
if (memType->getMemberComponents().size() == 1)
1810+
if (auto first =
1811+
dyn_cast<IdentTypeRepr>(memType->getMemberComponents().front()))
1812+
return {base, first};
1813+
return {nullptr, nullptr};
1814+
}
1815+
17951816
DeclNameRef UnresolvedMacroReference::getMacroName() const {
17961817
if (auto *expansion = pointer.dyn_cast<FreestandingMacroExpansion *>())
17971818
return expansion->getMacroName();
17981819
if (auto *attr = pointer.dyn_cast<CustomAttr *>()) {
1799-
auto *identTypeRepr = dyn_cast_or_null<IdentTypeRepr>(attr->getTypeRepr());
1800-
if (!identTypeRepr)
1820+
auto [_, member] = destructureMacroRefTypeRepr(attr->getTypeRepr());
1821+
if (!member)
18011822
return DeclNameRef();
1802-
return identTypeRepr->getNameRef();
1823+
return member->getNameRef();
18031824
}
18041825
llvm_unreachable("Unhandled case");
18051826
}
@@ -1812,14 +1833,38 @@ SourceLoc UnresolvedMacroReference::getSigilLoc() const {
18121833
llvm_unreachable("Unhandled case");
18131834
}
18141835

1836+
DeclNameRef UnresolvedMacroReference::getModuleName() const {
1837+
if (auto *expansion = pointer.dyn_cast<FreestandingMacroExpansion *>())
1838+
return expansion->getModuleName();
1839+
if (auto *attr = pointer.dyn_cast<CustomAttr *>()) {
1840+
auto [base, _] = destructureMacroRefTypeRepr(attr->getTypeRepr());
1841+
if (!base)
1842+
return DeclNameRef();
1843+
return base->getNameRef();
1844+
}
1845+
llvm_unreachable("Unhandled case");
1846+
}
1847+
1848+
DeclNameLoc UnresolvedMacroReference::getModuleNameLoc() const {
1849+
if (auto *expansion = pointer.dyn_cast<FreestandingMacroExpansion *>())
1850+
return expansion->getModuleNameLoc();
1851+
if (auto *attr = pointer.dyn_cast<CustomAttr *>()) {
1852+
auto [base, _] = destructureMacroRefTypeRepr(attr->getTypeRepr());
1853+
if (!base)
1854+
return DeclNameLoc();
1855+
return base->getNameLoc();
1856+
}
1857+
llvm_unreachable("Unhandled case");
1858+
}
1859+
18151860
DeclNameLoc UnresolvedMacroReference::getMacroNameLoc() const {
18161861
if (auto *expansion = pointer.dyn_cast<FreestandingMacroExpansion *>())
18171862
return expansion->getMacroNameLoc();
18181863
if (auto *attr = pointer.dyn_cast<CustomAttr *>()) {
1819-
auto *identTypeRepr = dyn_cast_or_null<IdentTypeRepr>(attr->getTypeRepr());
1820-
if (!identTypeRepr)
1864+
auto [_, member] = destructureMacroRefTypeRepr(attr->getTypeRepr());
1865+
if (!member)
18211866
return DeclNameLoc();
1822-
return identTypeRepr->getNameLoc();
1867+
return member->getNameLoc();
18231868
}
18241869
llvm_unreachable("Unhandled case");
18251870
}
@@ -1829,8 +1874,10 @@ SourceRange UnresolvedMacroReference::getGenericArgsRange() const {
18291874
return expansion->getGenericArgsRange();
18301875

18311876
if (auto *attr = pointer.dyn_cast<CustomAttr *>()) {
1832-
auto *typeRepr = attr->getTypeRepr();
1833-
auto *genericTypeRepr = dyn_cast_or_null<GenericIdentTypeRepr>(typeRepr);
1877+
auto [_, member] = destructureMacroRefTypeRepr(attr->getTypeRepr());
1878+
if (!member)
1879+
return SourceRange();
1880+
auto *genericTypeRepr = dyn_cast_or_null<GenericIdentTypeRepr>(member);
18341881
if (!genericTypeRepr)
18351882
return SourceRange();
18361883

@@ -1845,8 +1892,10 @@ ArrayRef<TypeRepr *> UnresolvedMacroReference::getGenericArgs() const {
18451892
return expansion->getGenericArgs();
18461893

18471894
if (auto *attr = pointer.dyn_cast<CustomAttr *>()) {
1848-
auto *typeRepr = attr->getTypeRepr();
1849-
auto *genericTypeRepr = dyn_cast_or_null<GenericIdentTypeRepr>(typeRepr);
1895+
auto [_, member] = destructureMacroRefTypeRepr(attr->getTypeRepr());
1896+
if (!member)
1897+
return {};
1898+
auto *genericTypeRepr = dyn_cast_or_null<GenericIdentTypeRepr>(member);
18501899
if (!genericTypeRepr)
18511900
return {};
18521901

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);
@@ -3984,13 +3984,13 @@ namespace {
39843984
}
39853985

39863986
/// Lookup all macros with the given macro name.
3987-
SmallVector<OverloadChoice, 1>
3988-
lookupMacros(Identifier macroName,
3989-
FunctionRefKind functionRefKind,
3990-
MacroRoles roles) {
3987+
SmallVector<OverloadChoice, 1> lookupMacros(Identifier moduleName,
3988+
Identifier macroName,
3989+
FunctionRefKind functionRefKind,
3990+
MacroRoles roles) {
39913991
SmallVector<OverloadChoice, 1> choices;
3992-
auto results = namelookup::lookupMacros(
3993-
CurDC, DeclNameRef(macroName), roles);
3992+
auto results = namelookup::lookupMacros(CurDC, DeclNameRef(moduleName),
3993+
DeclNameRef(macroName), roles);
39943994
for (const auto &result : results) {
39953995
OverloadChoice choice = OverloadChoice(Type(), result, functionRefKind);
39963996
choices.push_back(choice);
@@ -4012,10 +4012,11 @@ namespace {
40124012
CS.associateArgumentList(locator, expr->getArgs());
40134013

40144014
// Look up the macros with this name.
4015+
auto moduleIdent = expr->getModuleName().getBaseIdentifier();
40154016
auto macroIdent = expr->getMacroName().getBaseIdentifier();
40164017
FunctionRefKind functionRefKind = FunctionRefKind::SingleApply;
4017-
auto macros = lookupMacros(
4018-
macroIdent, functionRefKind, expr->getMacroRoles());
4018+
auto macros = lookupMacros(moduleIdent, macroIdent, functionRefKind,
4019+
expr->getMacroRoles());
40194020
if (macros.empty()) {
40204021
ctx.Diags.diagnose(expr->getMacroNameLoc(), diag::macro_undefined,
40214022
macroIdent)

lib/Sema/TypeCheckMacros.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1831,8 +1831,8 @@ ConcreteDeclRef ResolveMacroRequest::evaluate(Evaluator &evaluator,
18311831
// When a macro is not found for a custom attribute, it may be a non-macro.
18321832
// So bail out to prevent diagnostics from the contraint system.
18331833
if (macroRef.getAttr()) {
1834-
auto foundMacros = namelookup::lookupMacros(
1835-
dc, macroRef.getMacroName(), roles);
1834+
auto foundMacros = namelookup::lookupMacros(dc, macroRef.getModuleName(),
1835+
macroRef.getMacroName(), roles);
18361836
if (foundMacros.empty())
18371837
return ConcreteDeclRef();
18381838
}

0 commit comments

Comments
 (0)