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. Intyields incrementing transformations (e.g. foo -> bar(0), foobar -> bar(1), foobarfoo -> bar(2))
  • Replacing return ["case bar(Bool)"] with return [DeclSyntax(try EnumCaseDeclSyntax("case bar(Int)"))] seems to have no effect.

I'm not sure if this is this an unexpected use case for Macros, or if I am doing something incorrectly.


I believe this is a bug. Additionally, I've noticed that after calling bar(Int) once in the file, foo won't be transformed anymore.

1 Like

@ssly Thanks! Yes, we can confirm that using .bar in the example app 'fixes' the issue. It didn't seem to work in a more complex app, though.
Yeah, it sure feels like a bug.

I've logged an Issue on the Swift repo.

1 Like