Skip to content

Comments

fix: don’t format mixed macro args (items + non-items) (#6629)#6637

Open
giammirove wants to merge 3 commits intorust-lang:mainfrom
giammirove:master
Open

fix: don’t format mixed macro args (items + non-items) (#6629)#6637
giammirove wants to merge 3 commits intorust-lang:mainfrom
giammirove:master

Conversation

@giammirove
Copy link

Fixes #6629

Problem

The following code:

macro_rules! reproduce {
    (type Fail = $ty:ty; arr = $($arr:expr),*) => {
        ( vec![$($arr),+] )
    };
}

fn main() {
    reproduce!(type Fail = char; arr = 1);
}

is formatted as:

macro_rules! reproduce {
    (type Fail = $ty:ty; arr = $($arr:expr),*) => {
        ( vec![$($arr),+] )
    };
}

fn main() {
    reproduce!(type Fail = char;, arr = 1);
}

Notice the , right after ; in the macro invocation.
Making the formatted code's syntax wrong.

Solution

When formatting a list of commented items into a list (write_list in src/lists.rs), do not add the comma if the item's entry ends with ;.

Changes

  • Modified write_list in src/lists.rs to avoid adding , if the argument ends with ;.
  • Added regression test case issue-6629.rs to prevent future regressions

@giammirove
Copy link
Author

I found an edge case for which my fix would break the code.

The following code:

macro_rules! reproduce {
    (type Fail = $ty:ty; arr = $($arr:expr),+) => {
        ( vec![$($arr),+] )
    };
    ( $expr:expr, $($arr:item),+) => {
        1
    };
}
reproduce!(type Fail = char; arr = 1);

is rewritten as:

reproduce!(type Fail = char;, arr = 1);

which is not valid code.

The problem is related to mixed argument types (items and non items).
The code responsible for parsing the macro arguments is parse_macro_args in src/parse/macros/mod.rs. parse_macro_args interpret type Fail = char; as an item, while arr = 1 as an array of expr.
While parse_macro_args parses the arguments, it does not detect any ;, since ; is part of the item (items are self-terminating).
Therefore, the arguments are later treated as vec![1,2,3,4], and write_list will append , after every argument, breaking the code.
My previous fix was to avoid appending , after ;. Such a fix would break other valid code, see:

reproduce!(23, type Fail = char;, type Fail = char;);

is rewritten as:

reproduce!(23, type Fail = char; type Fail = char;);

which is not valid code, since the macro accepts arguments like ($($arr:item),+).

The problem is therefore related to the presence of both item and non item arguments.
Currently, no implementation accounts for this case scenario in rewrite_macro_inner in src/macros.rs.
The current solution uses a conservative approach, where mixed macro arguments are not formatted.

@giammirove giammirove changed the title fix: do not add commas after ';' in macro args (#6629) fix: don’t format mixed macro args (items + non-items) (#6629) Aug 17, 2025
Items in macro input are self-terminating (their own `;`/`}` closes them),
so treating mixed argument lists as comma lists leads rustfmt to invent a
comma after an item:
```
reproduce!(type Fail = char; arr = 1);
// became
reproduce!(type Fail = char;, arr = 1); // invalid
```
`parse_macro_args` correctly parses `type Fail = char;` as an item and
`arr = 1` as exprs, but later `rewrite_macro_inner`/`write_list` assumes a
comma-separated list and appends a comma after the item.

Fix: be conservative, if a macro invocation contains at least one `$item`
and at least one non-`$item`, do not format it. Keep existing behavior for
all-items (use items path) and no-items (use list formatting).

This avoids inventing commas after items without breaking valid cases like:
```
reproduce!(23, type Fail = char;, type Fail = char;);
```
@jieyouxu jieyouxu added S-waiting-on-review Status: awaiting review from the assignee but also interested parties. F-no-formatting-impact Expected formatting impact: none or not applicable and removed pr-not-reviewed labels Feb 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

F-no-formatting-impact Expected formatting impact: none or not applicable S-waiting-on-review Status: awaiting review from the assignee but also interested parties.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

rustfmt breaks macro code

3 participants