'body' macro cannot be attached to property

I'm trying out the new function body macros. I'm attempting to attach the macro to a computed variable, which I believe was part of the proposal:

When using the shorthand syntax for get-only properties, a function body macro can be applied to the property itself

However, when I do I get the error 'body' macro cannot be attached to property. Is attaching a body macro to a get only property still a supported use case?

Complete code:

// plugin

import SwiftSyntax
import SwiftCompilerPlugin
@_spi(ExperimentalLanguageFeature) import SwiftSyntaxMacros

@main
struct Plugin: CompilerPlugin {
    let providingMacros: [Macro.Type] = [
        HelloMacro.self,
    ]
}

struct HelloMacro: BodyMacro {
    static func expansion(
        of node: AttributeSyntax,
        providingBodyFor declaration: some DeclSyntaxProtocol & WithOptionalCodeBlockSyntax,
        in context: some MacroExpansionContext
    ) throws -> [CodeBlockItemSyntax] {
        [
            """
            "hello," + \(declaration.body!)
            """
        ]
    }
}

// package

@attached(body)
public macro Hello() = #externalMacro(module: "Plugin", type: "HelloMacro")

struct Test {
    @Hello
    var helloFoo: String {
        "Foo"
    }
}

This is all on Xcode 16 beta 4

You probably want to make HelloMacro an accessor macro so it can generate accessor (getters, setters, …) for properties.

Hmm - that doesn't seem to work; if HelloMacro explicitly adds a getter, I get the compilation error:

🛑 Variable already has a getter

If HelloMacro just adds a statement like print("hello!") it doesn't seem to get executed despite generating the following code:

@Hello
var test: String {
    "Foo"
}

// expands to
var test: String {
    print("hello!")
    "Foo"
}

print(test) // prints just "Foo" not "hello!"

I'm trying to do something similar to the following example from the proposal - this should be a BodyMacro, no?

@Logged var area: Double {
  return length * width
}
1 Like

I think you’re missing a return statement on the last expression. I’m not sure if that’d fix the error you’re getting g though.

The return doesn't affect things - with or without it always returns "Foo" but does not call print("hello!")

Also - that example was using the accessor macro; I thought this would be a great use case for BodyMacro but when I try to use one, I get the error I mentioned above 'body' macro cannot be attached to property.

I'm assuming this is a bug in the compiler warning? Since I was under the impression we could attach BodyMacros to computed variables / variable getters.

1 Like

I just checked and function body macros not working for get-only properties is a known issue.

2 Likes

Got it - thanks for looking into it @ahoppen :pray:t3: look forward to taking things for a spin once it’s fixed

@ahoppen is this reported as an issue somewhere? I'm curious to know more about it, but I can't find anything more than this thread.

I don’t think we had a GitHub issue for it, now we do: Body macro can’t be attached to variables · Issue #75715 · swiftlang/swift · GitHub

2 Likes

Hi! Any movement on this? Seems like this is still an issue in the latest Xcode, Version 16.0 (16A242d).