I raised this idea in another thread but that thread seems to have died out and I feel like this merits a little more discussion.
I suggested allowing macros to extend other types (not limited to the attached type, like now) provided the macro definition - or perhaps the call site - specifies what the extended type(s) will be.
The reason that's always given for the current restriction on extension macros only being allowed to extend the attached type is so the compiler can be smart about when to expand the macros. It seems to me like this idea would satisfy that requirement.
So I imagine something like this, where the macro definition includes the extended type:
then this: #environmentValue("myValue", type: Int.self, key: MyKey.self)
expands to the usual SwiftUI environment value property:
extension EnvironmentValues {
var myValue: Int {
get { self[MyKey.self] }
set { self[MyKey.self] = newValue }
}
}
And perhaps we could also allow the macro invocation to specify the extended type, like if you have a protocol where implementing it tends to be very boilerplate-ish: #addMyProtocol(to: OtherType.self)
Does this seem workable? Is there any reason why either of these (specifying the extended type in declaration vs invocation) doesn't give the compiler the information it needs to intelligently and conservatively expand macros? What other considerations do we have?
Yes, but it forces the user of the macro to know which type is being extended, as well as the exact conditions in the where clause. One of the reasons to create a macro for implementing an extension is specifically to abstract away the boilerplate of the where clause or to automatically determine which type needs to be extended.
However, I did notice one odd thing when I tried it: If the right brace is on the same line as the left, as show, the added decls appeared outside of the extension: