Peer Macro expansion fails to compile

I have this macro declaration to be attached on protocols

@attached(peer, names: prefixed(Hashable))
public macro SelfHashable() = #externalMacro(module: "MacrosImplementation", type: "SelfHashable")

that

@SelfHashable
protocol P: Hashable {}

expands to

protocol P: Hashable {}

@propertyWrapper
struct HashableP: Hashable { // Compiler complains here
    let wrappedValue: any P
    static func == (lhs: HashableP, rhs: HashableP) -> Bool {
        true // to be lhs.wrappedValue.isEqual(to: rhs.wrappedValue)
    }
    func hash(into hasher: inout Hasher) {
        hasher.combine(wrappedValue)
    }
}

The problem is that compiler fails to compile the expansion with

struct HashableP: Hashable { // Type 'HashableP' does not conform to protocol 'Equatable'

I believe that my case isn't related to extension macros, nor member macro conformance. I hope this is just a bug that can be fixed. Or am I doing something wrong?

Hi there!

Could you also share you macro implementation?

With omitted Extractor and Diagnostic utils.

import SwiftDiagnostics
import SwiftSyntax
import SwiftSyntaxBuilder
import SwiftSyntaxMacros

public enum SelfHashable: PeerMacro {
    
    public static func expansion(
        of node: SwiftSyntax.AttributeSyntax,
        providingPeersOf declaration: some SwiftSyntax.DeclSyntaxProtocol,
        in context: some SwiftSyntaxMacros.MacroExpansionContext
    ) throws -> [SwiftSyntax.DeclSyntax] {
        do {
            guard let protocolDeclSyntax = declaration.as(ProtocolDeclSyntax.self) else {
                throw Diagnostic.invalidDeclaration(declaration, expected: [ProtocolDeclSyntax.self]).error(at: node)
            }
            let protocolName = try Extract.protocolName(protocolDeclSyntax)
            let expansionTypeName = "Hashable\(protocolName)"

            let declSyntax = DeclSyntax(
                """
                @propertyWrapper
                struct \(raw: expansionTypeName): Hashable {
                    let wrappedValue: any \(raw: protocolName)
                    static func ==(lhs: \(raw: expansionTypeName), rhs: \(raw: expansionTypeName)) -> Bool {
                        true // lhs.wrappedValue.isEqual(to: rhs.wrappedValue)
                    }
                    func hash(into hasher: inout Hasher) {
                        hasher.combine(wrappedValue)
                    }
                }
                """

            )
            return [declSyntax]
        } catch {
            throw error.diagnosticError(at: node)
        }
    }
}

Thank you!

To me, the implementation appears to be correct. If I had to guess, I'd say that's a bug. You might consider filing a GitHub issue here.

Ok I tried it in Xcode 15.1 beta (15C5028h) and it works so it seems to be fixed already.

Perhaps it was same bug as The static method generated by ExtensionMacro is not visible to compiler.

Thanks for your effort.

Great to hear that! Thanks for the information!