The static method generated by ExtensionMacro is not visible to compiler

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"
    }
}

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.

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

I made a repository that reproduces the problem on Xcode 15.0 beta 8 and swift-DEVELOPMENT-SNAPSHOT-2023-08-23-a

1 Like

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.

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.

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.

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?

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?

Okay, I created an issue

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