Skip to content

Commit 5f57ec8

Browse files
authored
Merge pull request swiftlang#66317 from DougGregor/macro-expand-only-module-scope-lookup
Only inject macro-introduced operators into module scope
2 parents 386c180 + 88dd6fc commit 5f57ec8

File tree

3 files changed

+102
-0
lines changed

3 files changed

+102
-0
lines changed

lib/AST/Module.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,13 @@ void SourceLookupCache::populateAuxiliaryDeclCache() {
403403
for (auto macroNames : introducedNames) {
404404
auto macroRef = macroNames.getFirst();
405405
for (auto name : macroNames.getSecond()) {
406+
407+
// If this macro isn't in a module-scope context, and the introduced
408+
// name isn't an operator, we shouldn't be able to see it.
409+
if (!decl->getDeclContext()->isModuleScopeContext() &&
410+
!name.getBaseName().isOperator())
411+
continue;
412+
406413
auto *placeholder = MissingDecl::forUnexpandedMacro(macroRef, decl);
407414
name.addToLookupTable(TopLevelAuxiliaryDecls, placeholder);
408415
}
@@ -485,6 +492,12 @@ void SourceLookupCache::lookupValue(DeclName Name, NLKind LookupKind,
485492
for (auto *unexpandedDecl : unexpandedDecls) {
486493
unexpandedDecl->forEachMacroExpandedDecl(
487494
[&](ValueDecl *decl) {
495+
// If the declaration is not a module-scope declaration, and
496+
// isn't an operator, ignore it.
497+
if (!decl->getDeclContext()->isModuleScopeContext() &&
498+
!decl->getName().getBaseName().isOperator())
499+
return;
500+
488501
if (decl->getName().matchesRef(Name)) {
489502
if (macroExpandedDecls.insert(decl).second)
490503
Result.push_back(decl);

test/Macros/Inputs/syntax_macro_definitions.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,3 +1531,37 @@ public struct UseIdentifierMacro: DeclarationMacro {
15311531
]
15321532
}
15331533
}
1534+
1535+
public struct StaticFooFuncMacro: DeclarationMacro {
1536+
public static func expansion(
1537+
of node: some FreestandingMacroExpansionSyntax,
1538+
in context: some MacroExpansionContext
1539+
) throws -> [DeclSyntax] {
1540+
return [
1541+
"static func foo() {}",
1542+
]
1543+
}
1544+
}
1545+
1546+
public struct SelfAlwaysEqualOperator: DeclarationMacro {
1547+
public static func expansion(
1548+
of node: some FreestandingMacroExpansionSyntax,
1549+
in context: some MacroExpansionContext
1550+
) throws -> [DeclSyntax] {
1551+
return [
1552+
"static func ==(lhs: Self, rhs: Bool) -> Bool { true }",
1553+
]
1554+
}
1555+
}
1556+
1557+
extension SelfAlwaysEqualOperator: MemberMacro {
1558+
public static func expansion(
1559+
of node: AttributeSyntax,
1560+
providingMembersOf decl: some DeclGroupSyntax,
1561+
in context: some MacroExpansionContext
1562+
) throws -> [DeclSyntax] {
1563+
return [
1564+
"static func ==(lhs: Self, rhs: Bool) -> Bool { true }",
1565+
]
1566+
}
1567+
}

test/Macros/macro_expand.swift

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,3 +425,58 @@ func testLocalVarsFromDeclarationMacros() {
425425
struct TakesVariadic {
426426
#emptyDecl("foo", "bar")
427427
}
428+
429+
// Funkiness with static functions introduced via macro expansions.
430+
@freestanding(declaration, names: named(foo())) public macro staticFooFunc() = #externalMacro(module: "MacroDefinition", type: "StaticFooFuncMacro")
431+
@freestanding(declaration, names: arbitrary) public macro staticFooFuncArbitrary() = #externalMacro(module: "MacroDefinition", type: "StaticFooFuncMacro")
432+
433+
class HasAnExpandedStatic {
434+
#staticFooFunc()
435+
}
436+
437+
class HasAnExpandedStatic2 {
438+
#staticFooFuncArbitrary()
439+
}
440+
441+
func testHasAnExpandedStatic() {
442+
#if TEST_DIAGNOSTICS
443+
foo() // expected-error{{cannot find 'foo' in scope}}
444+
#endif
445+
}
446+
447+
@freestanding(declaration, names: named(==)) public macro addSelfEqualsOperator() = #externalMacro(module: "MacroDefinition", type: "SelfAlwaysEqualOperator")
448+
@freestanding(declaration, names: arbitrary) public macro addSelfEqualsOperatorArbitrary() = #externalMacro(module: "MacroDefinition", type: "SelfAlwaysEqualOperator")
449+
@attached(member, names: named(==)) public macro AddSelfEqualsMemberOperator() = #externalMacro(module: "MacroDefinition", type: "SelfAlwaysEqualOperator")
450+
@attached(member, names: arbitrary) public macro AddSelfEqualsMemberOperatorArbitrary() = #externalMacro(module: "MacroDefinition", type: "SelfAlwaysEqualOperator")
451+
452+
struct HasEqualsSelf {
453+
#addSelfEqualsOperator
454+
}
455+
456+
struct HasEqualsSelf2 {
457+
#addSelfEqualsOperatorArbitrary
458+
}
459+
460+
@AddSelfEqualsMemberOperator
461+
struct HasEqualsSelf3 {
462+
}
463+
464+
@AddSelfEqualsMemberOperatorArbitrary
465+
struct HasEqualsSelf4 {
466+
}
467+
468+
func testHasEqualsSelf(
469+
x: HasEqualsSelf, y: HasEqualsSelf2, z: HasEqualsSelf3, w: HasEqualsSelf4
470+
) {
471+
_ = (x == true)
472+
_ = (y == true)
473+
#if TEST_DIAGNOSTICS
474+
// FIXME: This is technically a bug, because we should be able to find the
475+
// == operator introduced through a member operator. However, we might
476+
// want to change the rule rather than implement this.
477+
_ = (z == true) // expected-error{{binary operator '==' cannot be applied to operands}}
478+
// expected-note@-1{{overloads for '==' exist with these partially matching parameter lists}}
479+
_ = (w == true) // expected-error{{binary operator '==' cannot be applied to operands}}
480+
// expected-note@-1{{overloads for '==' exist with these partially matching parameter lists}}
481+
#endif
482+
}

0 commit comments

Comments
 (0)