red_beeard
(Alexander)
1
Hi, I am using ExtensionMacro to generate static functions and properties. When I try to access a static property (function) from another file, I get an error: "Type 'TypeName' has no member 'member'". But when accessing a property of a type, everything works correctly.
The problem disappears if the type was initialized before accessing the static one (I haven't checked the other). For example, if you swap these lines.
This problem is similar to Protocol extension method added by ExtensionMacro is not visible to compiler · Issue #67989 · apple/swift · GitHub
Snippet with problem
// Problem
print(Episode.descr)
print(Episode().descr2)
// Correct
print(Episode().descr2)
print(Episode.descr)
Macro
@attached(extension, names: named(descr), named(descr2))
public macro Demo() = #externalMacro(module: "MacroPlugin", type: "DemoMacro")
public struct DemoMacro: ExtensionMacro {
// MARK: - ExtensionMacro
public static func expansion(
of node: AttributeSyntax,
attachedTo declaration: some DeclGroupSyntax,
providingExtensionsOf type: some TypeSyntaxProtocol,
conformingTo protocols: [TypeSyntax],
in context: some MacroExpansionContext
) throws -> [ExtensionDeclSyntax] {
let members = try MemberBlockSyntax {
try VariableDeclSyntax("static var descr: String") {
"\"5\""
}
try VariableDeclSyntax("var descr2: String") {
"\"5\""
}
}
return [ExtensionDeclSyntax(extendedType: type, memberBlock: members)]
}
}
Structure
@Demo
struct Episode {
var id: Int
var name: String
var airDate: Date
var episode: String
var characters: [String]?
var url: String
var created: String
enum CodingKeys: String, CodingKey {
case id, name
case airDate
case episode, characters, url, created
}
}
Expanded macro
extension Episode {
static var descr: String {
"5"
}
var descr2: String {
"5"
}
}
ahoppen
(Alex Hoppen)
2
It looks like this issue has already been fixed. I was able to reproduce it with Xcode 15.0 beta 8 but not with the swift-DEVELOPMENT-SNAPSHOT-2023-08-23-a.
red_beeard
(Alexander)
3
I'm currently using Xcode 15.0 beta 8 and swift-syntax from commit b57df1e, which matches swift-DEVELOPMENT-SNAPSHOT-2023-08-23-a. The problem continues to reproduce for me.
I also tried 13f113e (swift-DEVELOPMENT-SNAPSHOT-2023-09-02-a), but the problem remains
red_beeard
(Alexander)
4
I made a repository that reproduces the problem on Xcode 15.0 beta 8 and swift-DEVELOPMENT-SNAPSHOT-2023-08-23-a
1 Like
jjrscott
(John Scott)
5
Continuses to fail on the latest swift-DEVELOPMENT-SNAPSHOT-2023-09-04-a. I agree it's not an Xcode 15b8 issues as I can produce functioning code by other means.
ahoppen
(Alex Hoppen)
6
Oh, sorry, I should have been clearer. I meant that it doesn’t reproduce with the swift-DEVELOPMENT-SNAPSHOT-2023-08-23-a toolchain you can download from swift.org. The version of swift-syntax you are using should be more or less irrelevant here.
red_beeard
(Alexander)
7
Thanks for the clarification. I really didn't understand what needed to be installed. I tried to switch toolchain tea toolchain to swift-DEVELOPMENT-SNAPSHOT-2023-08-23-a, but got the error Using global toolchain override 'Swift Development Snapshot 2023-08-23 (a)'. And switching through terminal commands was not successful. Apparently, I have to wait for the stable version of Xcode to be released.
red_beeard
(Alexander)
8
Hi, I tried to run this code in Xcode 15 Release Candidate but got the same error.
Below is the version of swift that is displayed in Toolchain for this version of Xcode.
red_beeard@MacBook-Pro-Alex ~ % /Applications/Xcode-15.0.0.0-release-candidate.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-frontend ; exit;
Welcome to Apple Swift version 5.9 (swiftlang-5.9.0.0.128.108 clang-1500.0.40.1).
Is the problem supposed to be fixed in this version? Or is an irrelevant version of Toolchain also being used?
ahoppen
(Alex Hoppen)
9
Hmm, interesting. I just tried again and are able to reproduce it with swift-DEVELOPMENT-SNAPSHOT-2023-08-23-a again. Could you file a bug for this at Sign in to GitHub · GitHub?
I'm seeing the same issue with Xcode 15 with static functions not just properties.
Demo
/// Foo.swift
@defaultProviding(of: Bar.self, value: Bar())
protocol Foo { }
struct Bar: Foo { }
let t: Foo = .default() // This works fine
/// main.swift
let m: Foo = .default() // Error: Type 'any Foo' has no member 'default'
Macro
@attached(extension, names: arbitrary)
public macro defaultProviding<T>(of _: T.Type, value: T) = #externalMacro(module: "DefaultProvidingMacros", type: "DefaultProvidingMacro")
public struct DefaultProvidingMacro: ExtensionMacro {
public static func expansion(of node: AttributeSyntax, attachedTo declaration: some DeclGroupSyntax, providingExtensionsOf type: some TypeSyntaxProtocol, conformingTo protocols: [TypeSyntax], in context: some MacroExpansionContext) throws -> [ExtensionDeclSyntax] {
guard
case .argumentList(let list) = node.arguments,
let t = list.first?.expression.as(MemberAccessExprSyntax.self),
let t1 = t.base?.as(DeclReferenceExprSyntax.self)?.baseName,
let expr = list.last?.expression
else {
fatalError("compiler bug: the macro does not have any arguments")
}
guard let decl = declaration.as(ProtocolDeclSyntax.self) else {
fatalError("not a protocol")
}
return [
.init(
extendedType: IdentifierTypeSyntax(name: decl.name),
memberBlock: .init {
FunctionDeclSyntax(
modifiers: [.init(name: .keyword(.static))],
name: .identifier("`default`"),
signature: .init(
parameterClause: .init(parameters: []),
returnClause: .init(type: IdentifierTypeSyntax(name: decl.name))
),
genericWhereClause: .init(requirements: [
.init(requirement: .sameTypeRequirement(
.init(
leftType: IdentifierTypeSyntax(name: .keyword(.Self)),
equal: .binaryOperator("=="),
rightType: IdentifierTypeSyntax(name: t1))))
])
) {
expr
}
})
]
}
}
I downloaded swift-DEVELOPMENT-SNAPSHOT-2024-06-11-a. It fixes the problem