Usually extension macros are attached macros, e.g.
// Declaration:
@attached(extension, conformances: CustomDebugStringConvertible)
@attached(member, names: named(debugDescription))
public macro OptionSetDebugDescription() = #externalMacro(module: "MyMacros", type: "OptionSetDebugDescriptionMacro")
// Usage:
@OptionSetDebugDescription
struct OpenFlags: OptionSet { ... }
My macro works well if I'm defining a new type like that. However, I'd like to use it on pre-existing types, typically defined in C using NS_OPTIONS
, e.g.:
typedef NS_OPTIONS(NSUInteger, OpenFlags) {
OpenFlagsReadable = FREAD,
OpenFlagsWritable = FWRITE,
};
Neither of these work:
import struct MyCLibrary.OpenFlags
@OptionSetDebugDescription
struct OpenFlags: OptionSet {} // This defines a new type, unrelated to `MyCLibrary`
@OptionSetDebugDescription
extension OpenFlags {} // 'extension' macro cannot be attached to extension
And a freestanding macro also doesn't work. Even if you get the expansion to work correctly:
@freestanding(declaration, conformances: CustomDebugStringConvertible)
public macro OptionSetDebugDescription<T: OptionSet>(to _: T.Type) =
#externalMacro(module: "MyMacros", type: "OptionSetDebugDescriptionMacro")
#OptionSetDebugDescription(to: OpenFlags.self)
// Expands to:
// extension OpenFlags: CustomDebugStringConvertible {
// var debugDescription: String { ... }
//}
... the compiler will block it:
Macro expansion cannot introduce extension
This intentional limitation is why conformance macros were added in the first place, but they seem limited to new type declarations only.
Am I missing something?