I was trying to implement Assign if different using freestanding macro and I did succeed but kind of cheating using a closure because the freestanding macro is expected to return and expression.
#assign(b, to: a, if: !=) for example is expanded to:
{
if a != b {
a = b
}
}()
Is this the only way to currently do this? Any plans to lift this restriction with another kind of freestanding macro?
This is the only way to do this today. The early pitches for declaration macros had "code item" macros that could do this, and there's a partial implementation of the feature in the compiler behind an experimental feature flag (CodeItemMacros), but nobody has followed through with pitch/proposal/complete implementation. Personally, I haven't seen that many use cases for code-item macros vs. the other kinds, so I haven't looked into them further.
I have a use case for this kind of feature that might be valuable.
It's not possible to possible to wrap os log calls because OSLogMessage cannot be initiliazed from a String variable, it forces us to duplicate log lines to both log into Unified logging system and to Crashlytics for example.
I would like to use a macro to expand the boilerplate code that perform those 2 calls. It seems that only CodeItemMacro can achieve this but I might be wrong...
I created a macro for this exact same use case, and ended up using the same immediately-executed closure strategy described in the original post here, in order to consolidate the two expressions down to a single one.
Would completing the implementation of CodeItemMacros solve the need to add the {/* Generated code here */}() wrapper? Depending on the code before a macro containing the wrapper, it will occasionally get treated as a trailing closure and then fail with: .../swift-generated-sources/@__REDEACTED_MANGLED_NAME_.swift:1:1 Function type mismatch, declared as '@convention(thin) @substituted <τ_0_0> (@in_guaranteed MySwiftUIView) -> (@out τ_0_0, @error any Error) for <()>' but used as '@convention(thin) (@guaranteed { var String }) -> ()'
My use case is basically the same as schwa's but the wrapper option is causing a few issues, even a compiler crash on Xcode 16.3 beta 1.
One work around is to change the wrapper to ;{/* Generated code here */}(). Note the leading semicolon.
But it would be really nice to not have to use a work around in a work around :)