Skip to content

Allow peer macros on variables with multiple bindings in assertMacroExpansion#3342

Open
adityasingh2400 wants to merge 1 commit into
swiftlang:mainfrom
adityasingh2400:allow-peer-macro-multiple-bindings
Open

Allow peer macros on variables with multiple bindings in assertMacroExpansion#3342
adityasingh2400 wants to merge 1 commit into
swiftlang:mainfrom
adityasingh2400:allow-peer-macro-multiple-bindings

Conversation

@adityasingh2400

Copy link
Copy Markdown

assertMacroExpansion rejects a peer macro attached to a variable declaration with more than one binding, such as var a: Int, b: Int, raising "peer macro can only be applied to a single variable" before the macro is ever invoked. Reported in #3320.

This restriction dates back to #2154, when the rationale was that the compiler effectively disallowed this: it invoked the peer macro once per binding with the same syntax node, which generated the same peers twice and produced a redeclaration error. That is no longer the situation. The compiler now invokes a peer macro on such declarations and only diagnoses a problem if the macro itself emits conflicting declarations. A peer macro that returns no peers (the case in #3320), or that returns peers with unique names, compiles cleanly.

I verified this against the Swift 6.3 toolchain by building a peer macro and applying it to var a: Int = 1, b: Int = 2:

  • Returning [] compiles and runs with no diagnostics.
  • Returning a declaration with a context.makeUniqueName based name compiles cleanly.
  • Returning a fixed-name declaration fails only with "invalid redeclaration", and the note shows the macro was expanded on each property, confirming the macro is invoked rather than rejected outright.

So the guard made assertMacroExpansion emit a false-positive diagnostic for code the compiler accepts, which makes it an unreliable oracle when testing peer macros on multi-binding variables.

The fix removes the binding-count guard from both expandPeerMacroMember and expandPeerMacroCodeItem, so the peer macro runs on the whole declaration and its peers are emitted, matching the compiler. The now-unused peerMacroOnVariableWithMultipleBindings error case is dropped. The accessor-macro restriction is intentionally left untouched, since the compiler genuinely does not allow accessor macros on multi-binding variables.

The existing testPeerMacroOnVariableWithMultipleBindings is updated to assert that the peer is now emitted, and a new testPeerMacroReturningNoPeersOnVariableWithMultipleBindings covers the exact scenario from #3320. Both fail against the current code with the spurious diagnostic and pass after the change. The full SwiftSyntaxMacroExpansion test target (135 tests) passes.

…xpansion

assertMacroExpansion rejected peer macros attached to a variable
declaration with more than one binding (such as `var a: Int, b: Int`)
with the error "peer macro can only be applied to a single variable",
before the macro was ever invoked.

This restriction was added back when the compiler effectively disallowed
this by invoking the macro once per binding with the same syntax node,
which produced duplicate peers and a redeclaration error. That is no
longer the case: the compiler invokes a peer macro on such declarations
and only diagnoses a problem if the macro itself emits conflicting
declarations. A peer macro that returns no peers, or peers with unique
names, compiles cleanly. This was verified by building a peer macro
against the Swift 6.3 toolchain.

As a result, assertMacroExpansion produced a false-positive diagnostic
for code that the compiler accepts, making it an unreliable test oracle
for peer macros on multi-binding variables.

Remove the binding-count guard from both expandPeerMacroMember and
expandPeerMacroCodeItem so the peer macro runs and its peers are
emitted, matching the compiler. The corresponding error case is dropped
since it is no longer used. The accessor-macro restriction is left in
place because the compiler genuinely does not allow accessor macros on
multi-binding variables.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant