Stan_Smida
(Stan Smida)
October 20, 2023, 8:55am
1
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?
Matejkob
(Mateusz Bąk)
October 20, 2023, 9:03am
2
Hi there!
Could you also share you macro implementation?
Stan_Smida
(Stan Smida)
October 20, 2023, 9:12am
3
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)
}
}
}
Matejkob
(Mateusz Bąk)
October 20, 2023, 9:17am
4
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 .
Stan_Smida
(Stan Smida)
October 20, 2023, 12:38pm
5
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.
Matejkob
(Mateusz Bąk)
October 20, 2023, 12:40pm
6
Great to hear that! Thanks for the information!