Skip to content

Commit f12d1f8

Browse files
committed
[ASTScope] Adjust parent location for peer macro to after its attached decl.
Peer macro produce declarations that are semantically alongside the declaration to which the macro is attached. However, the source location used for constructing the scope tree was based on the attribute itself, which meant it was inside the scope of the declaration to which the macro was attached. This lead to incorrect unqualified name lookup; in the example that's now a test case, this meant that the `Self` of the protocol to which the macro was attached was visible from within the peer declaration. Hilarity (in the form of a type checker crash) ensued. Fix the location used for constructing the scope tree of peer macros to be right after the attached declaration. Fixes rdar://107228586.
1 parent 828de17 commit f12d1f8

File tree

4 files changed

+42
-1
lines changed

4 files changed

+42
-1
lines changed

lib/AST/ASTScopeCreation.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "swift/AST/SourceFile.h"
3131
#include "swift/AST/Stmt.h"
3232
#include "swift/AST/TypeRepr.h"
33+
#include "swift/Parse/Lexer.h"
3334
#include "swift/Basic/Debug.h"
3435
#include "swift/Basic/STLExtras.h"
3536
#include "llvm/Support/Compiler.h"
@@ -262,10 +263,19 @@ ASTSourceFileScope::ASTSourceFileScope(SourceFile *SF,
262263
case MacroRole::Declaration:
263264
case MacroRole::Accessor:
264265
case MacroRole::MemberAttribute:
265-
case MacroRole::Peer:
266266
case MacroRole::Conformance:
267267
parentLoc = expansion.getStartLoc();
268268
break;
269+
case MacroRole::Peer: {
270+
ASTContext &ctx = SF->getASTContext();
271+
SourceManager &sourceMgr = ctx.SourceMgr;
272+
const auto &generatedSourceInfo =
273+
*sourceMgr.getGeneratedSourceInfo(*SF->getBufferID());
274+
275+
ASTNode node = ASTNode::getFromOpaqueValue(generatedSourceInfo.astNode);
276+
parentLoc = Lexer::getLocForEndOfToken(sourceMgr, node.getEndLoc());
277+
break;
278+
}
269279
case MacroRole::Member: {
270280
// For synthesized member macros, take the end loc of the
271281
// enclosing declaration (before the closing brace), because

test/Macros/Inputs/macro_library.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,6 @@ public macro ObservableProperty() = #externalMacro(module: "MacroDefinition", ty
3535

3636
@attached(peer, names: overloaded)
3737
public macro addCompletionHandler() = #externalMacro(module: "MacroDefinition", type: "AddCompletionHandler")
38+
39+
@attached(peer, names: suffixed(Builder))
40+
public macro AddClassReferencingSelf() = #externalMacro(module: "MacroDefinition", type: "AddClassReferencingSelfMacro")

test/Macros/Inputs/syntax_macro_definitions.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,3 +1296,26 @@ public struct DefineAnonymousTypesMacro: DeclarationMacro {
12961296
]
12971297
}
12981298
}
1299+
1300+
public struct AddClassReferencingSelfMacro: PeerMacro {
1301+
public static func expansion(
1302+
of node: AttributeSyntax,
1303+
providingPeersOf declaration: some DeclSyntaxProtocol,
1304+
in context: some MacroExpansionContext
1305+
) throws -> [DeclSyntax] {
1306+
guard let protocolDecl = declaration.as(ProtocolDeclSyntax.self) else {
1307+
throw CustomError.message("Macro can only be applied to a protocol declarations.")
1308+
}
1309+
1310+
let className = "\(protocolDecl.identifier.text)Builder"
1311+
return [
1312+
"""
1313+
struct \(raw: className) {
1314+
init(_ build: (_ builder: Self) -> Self) {
1315+
_ = build(self)
1316+
}
1317+
}
1318+
"""
1319+
]
1320+
}
1321+
}

test/Macros/macro_expand_peers.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import macro_library
2525
#else
2626
@attached(peer, names: overloaded)
2727
macro addCompletionHandler() = #externalMacro(module: "MacroDefinition", type: "AddCompletionHandler")
28+
@attached(peer, names: suffixed(Builder))
29+
macro AddClassReferencingSelf() = #externalMacro(module: "MacroDefinition", type: "AddClassReferencingSelfMacro")
2830
#endif
2931

3032
struct S {
@@ -113,3 +115,6 @@ struct Main {
113115
// CHECK-EXEC: hahaha global
114116
}
115117
}
118+
119+
@AddClassReferencingSelf
120+
protocol MyProto { }

0 commit comments

Comments
 (0)