…but body macros cannot be composed together, so you can't have e.g. @Logged and @Traced on the same function, or either in combination with @Retrying etc.
That's a pretty notable limitation.
Could preamble macros be replaced with wrapper macros, which essentially expand like:
@Logged
func g(a: Int, b: Int) throws -> Int {
try add(a, b)
}
…to:
func g(a: Int, b: Int) throws -> Int {
log("Entering g(a: \(a), b: \(b))")
do {
let result = try {
try add(a, b)
}()
log("Exited g(a: \(a), b: \(b)) with result: \(result)")
return result
} catch {
log("Exited g(a: \(a), b: \(b)) with error: \(error)")
throw error
}
}
These compose more neatly since they naturally nest.
You can also see why it's highly desirable to have a macro for things like this, because there's quite a lot of boilerplate for this simple pattern.