Swift Macros: Adding an enum case with an associated value produces incorrect results

Reproduced in Xcode versions 15.0.1 and 15.1 beta 3.

If a Macro adds an enum case with an associated value, other cases are transformed at runtime. In the example below, the case foo is translated into the Macro-generated case bar(false).

There is lots of other strange behavior, such as:

  • Case declarations in the same file as the enum are not transformed. For example, in the code above, a function written in SimpleEnum.swift can produce SimpleEnum.foo, whereas functions in other files cannot (the declarations are transformed).
  • Manually-defined cases with associated values are not transformed. For example, a manually-defined case foobar(Bool) can be declared and used normally everywhere.
  • Additional enum cases without associated values get transformed to different cases. For example, if SimpleEnum has manual cases foo, foobar, and foobarfoo, and a Macro-generated bar(Bool), these transformations take place:
    • foo -> bar(false)
    • foobar -> bar(true)
    • foobarfoo -> foo
    • etc.
  • Not all associated value types in the Macro-generated case are treated the same. String associated values seems to work properly. Int yields incrementing transformations (e.g. foo -> bar(0), foobar -> bar(1), foobarfoo -> bar(2))

Radar: FB13417290

You have a self-inflicted issue. Watch WWDC video on how to correctly rewrite the syntax tree instead of replace the tree. https://developer.apple.com/wwdc23/10166

Also, Swift Forums has a Development > Macros topic area, where a bunch of folks with in-depth macro experience hang out.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hi @MobileTen. Thanks for your comment. I'm not sure what you mean by "rewrite" the tree rather than "replace" it, though. In your linked video, one thing Alex does differently is initialize DeclSyntax nodes using explicit initializers rather than using plain strings. I haven't noticed a difference, though. When I replace return ["case bar(Bool)"] with return [DeclSyntax(try EnumCaseDeclSyntax("case bar(Int)"))], I continue to see the same issue. Can you elaborate on what I'm doing incorrectly?

Swift Macros: Adding an enum case with an associated value produces incorrect results
 
 
Q