rust-lang / rust-lang/rustfmt

Invalid code when formatting `matches!()` expressions with leading pipe also for the first alternative

Open
#5,860 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

A-macros C-bug
Dominant language
Rust
Stars
7k
Forks
1.1k
Avg merge
2d 13h
Merged PRs (30d)
24

Description

When I format the following code using rustfmt src/cmds.rs (with rustfmt 1.5.2-stable (8ede3aa 2023-07-12)) I get invalid code.

Original valid code:

impl SwayrCommand {
    fn is_scripting_command(&self) -> bool {
        matches!(
            self,
            | SwayrCommand::GetWindowsAsJson { .. }
            | SwayrCommand::ForEachWindow { .. }
        )
    }
}

Invalid code after formatting:

impl SwayrCommand {
    fn is_scripting_command(&self) -> bool {
        matches!(self, |SwayrCommand::GetWindowsAsJson { .. }| {
            SwayrCommand::ForEachWindow { .. }
        })
    }
}

The issue seems to be caused by the pipe | before the first alternative which is probably uncommon but legal.


I hoped I could fix the subjectively strange indentation of matches!() where the 2nd to last alternative are indented much more than the first that way. I.e., that's what I get now

impl SwayrCommand {
    fn is_scripting_command(&self) -> bool {
        matches!(
            self,
            SwayrCommand::GetWindowsAsJson { .. }
                | SwayrCommand::ForEachWindow { .. }
                | SwayrCommand::ForEachWindow2 { .. }
                | SwayrCommand::ForEachWindow4 { .. }
        )
    }
}

and what would please me more would be

impl SwayrCommand {
    fn is_scripting_command(&self) -> bool {
        matches!(
            self,
            SwayrCommand::GetWindowsAsJson { .. }
            | SwayrCommand::ForEachWindow { .. }
            | SwayrCommand::ForEachWindow2 { .. }
            | SwayrCommand::ForEachWindow4 { .. }
        )
    }
}

and by prefixing even the first alternative with a pipe, I would get

impl SwayrCommand {
    fn is_scripting_command(&self) -> bool {
        matches!(
            self,
            | SwayrCommand::GetWindowsAsJson { .. }
            | SwayrCommand::ForEachWindow { .. }
            | SwayrCommand::ForEachWindow2 { .. }
            | SwayrCommand::ForEachWindow4 { .. }
        )
    }
}

which is as aesthetically pleasing as the wished-for version.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Run rustfmt src/cmds.rs using the shown matches! expression and compare the formatted output with the original valid code. Trace the rustfmt handling of matches! alternatives, then add regression coverage for a leading pipe; done means formatting preserves valid Rust rather than producing a closure-like invalid expression.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.