funct7
1
I have a macro that generates constant declarations, but those declarations seem not to be available in the code following the macro.
The following code demonstrates the issue:
@freestanding(declaration, names: arbitrary)
public macro constantInt(name: String) = #externalMacro(module: "AgentMacroMacros", type: "ConstantIntMacro")
// just checking if arbitrary identifiers has anything to do with it
@freestanding(declaration, names: named(intValue))
public macro constantIntValue() = #externalMacro(module: "AgentMacroMacros", type: "ConstantIntValueMacro")
The definitions:
public enum ConstantIntMacro : DeclarationMacro {
public static func expansion(
of node: some FreestandingMacroExpansionSyntax,
in context: some MacroExpansionContext) throws -> [DeclSyntax]
{
let str = node.argumentList.first!.expression.as(StringLiteralExprSyntax.self)!
// assume no interpolations for simplicity
guard case .stringSegment(let strSyntax) = str.segments.first else { fatalError() }
return ["let \(raw: strSyntax.content.text) = 0"]
}
}
public enum ConstantIntValueMacro : DeclarationMacro {
public static func expansion(of node: some FreestandingMacroExpansionSyntax, in context: some MacroExpansionContext) throws -> [DeclSyntax] {
["let intValue = 0"]
}
}
Client code:
func demo() {
#constantIntValue
#constantInt(name: "someInt")
intValue // error
someInt // error
}
Expanding the macros gives me this:

I'm wondering if constant declarations cannot be used in this manner, or if this is a bug.
vanvoorden
(Rick van Voorden)
2
Hmm… what happens when you use the declaration macro at the top level (outside the scope of the function). Same problem?
Have you tried building from the latest swift-syntax commit from main? Have you tried building from the latest Swift toolchain (from main)?
ahoppen
(Alex Hoppen)
3
It seems like declaring local variables with a macro is indeed not supported. I filed Declaration macros can’t introduce local variables · Issue #72968 · apple/swift · GitHub for it.
3 Likes
ahoppen
(Alex Hoppen)
4
Update: Declaration macros not being able to introduce local variables is intended, as described here: swift-evolution/proposals/0389-attached-macros.md at main · apple/swift-evolution · GitHub
Therefore, a macro used within a closure or function body can only introduce declarations using names produced by createUniqueName . This maintains the two-phase of checking macros where type checking and inference is performed without expanding the macro, then the macro is expanded and its result type-checked independently, with no ability to influence type inference further.
3 Likes