Skip to content

Match arm trailing whitespace triggering error; match arm lone comma before comment unformattable #5537

Open
@RuijieYu

Description

@RuijieYu

Hello, I am encountering a combination of two issues.

$ rustc --version
rustc 1.63.0 (4b91a6ea7 2022-08-08)
$ cargo fmt --version
rustfmt 1.5.1-stable (4b91a6e 2022-08-08)

To my understanding there is no config file in effect.

After a bit of research, I think this issue is tangentially related toe #5535, as both are somewhat related to unformattable code due to potential loss of comments.


The issues are demonstrated in the following snippet. Note that the first match arm has trailing comma on a separate line, and that the Err(()) expression on the second match arm has a few trailing spaces.

Snippet 1

enum A {
    A1,
    A2,
}

struct B { field : bool, unused: () }

fn main() {}

fn f(a: A, b: B) -> Result<(), ()> {
    match (a,b ) {
        // arm 1
        (A::A1, B { field: true, ..}) =>
            Ok(println!("A1 + B=T"))
,
        // arm 2
        _ => Err(()),    
    }
}

In this form, cargo fmt --check generates the following error regarding the space after Err(()), causing my IDE to not format the code at all:

$ cargo fmt --check
Diff in /home/user/.cache/cargo-temp/tmp-cM6RJ2/src/main.rs at line 3:
     A2,
 }

-struct B { field : bool, unused: () }
+struct B {
+    field: bool,
+    unused: (),
+}

 fn main() {}

error[internal]: left behind trailing whitespace
  --> /home/user/.cache/cargo-temp/tmp-cM6RJ2/src/main.rs:20:20:22
   |
20 |         _ => Err(()),
   |                      ^^^^^^^^
   |

warning: rustfmt has failed to format. See previous 1 errors.

As suggested by #5535, but I don't quite understand which comment would be lost and why.

$ cargo fmt --check -- --config=error_on_unformatted=true
Diff in /home/user/.cache/cargo-temp/tmp-cM6RJ2/src/main.rs at line 3:
     A2,
 }

-struct B { field : bool, unused: () }
+struct B {
+    field: bool,
+    unused: (),
+}

 fn main() {}

error[internal]: not formatted because a comment would be lost
  --> /home/user/.cache/cargo-temp/tmp-cM6RJ2/src/main.rs:11
   |
11 |     match (a,b ) {
   |
   = note: set `error_on_unformatted = false` to suppress the warning against comments or string literals

error[internal]: left behind trailing whitespace
  --> /home/user/.cache/cargo-temp/tmp-cM6RJ2/src/main.rs:20:20:22
   |
20 |         _ => Err(()),
   |                      ^^^^
   |

warning: rustfmt has failed to format. See previous 2 errors.

After I remove the trailing spaces after Err(()) from snippet 1, the following is the formatted snippet.

Snippet 2

enum A {
    A1,
    A2,
}

struct B {
    field: bool,
    unused: (),
}

fn main() {}

fn f(a: A, b: B) -> Result<(), ()> {
    match (a,b ) {
        // arm 1
        (A::A1, B { field: true, ..}) =>
            Ok(println!("A1 + B=T"))
,
        // arm 2
        _ => Err(()),
    }
}

Note that the comma stays unchanged, whereas I expect it to be at the right of Ok(..). Even if I add spaces before the comma, it is never formatted to join the Ok(..) line. Also note that (a,b ) is not formatted.

Now as I format with error_on_unformatted:

$ cargo fmt --check -- --config=error_on_unformatted=true
error[internal]: not formatted because a comment would be lost
  --> /home/user/.cache/cargo-temp/tmp-cM6RJ2/src/main.rs:14
   |
14 |     match (a,b ) {
   |
   = note: set `error_on_unformatted = false` to suppress the warning against comments or string literals

warning: rustfmt has failed to format. See previous 1 errors.

When I join the comma with the previous line from snippet 2, the following is the formatted snippet.

Snippet 3

enum A {
    A1,
    A2,
}

struct B {
    field: bool,
    unused: (),
}

fn main() {}

fn f(a: A, b: B) -> Result<(), ()> {
    match (a, b) {
        // arm 1
        (A::A1, B { field: true, .. }) => Ok(println!("A1 + B=T")),
        // arm 2
        _ => Err(()),
    }
}

Notice that now the comma and Ok(..) are now joined together.


When I instead remove the "arm 2" comment from snippet 2, the following is the formatted snippet.

Snippet 4

enum A {
    A1,
    A2,
}

struct B {
    field: bool,
    unused: (),
}

fn main() {}

fn f(a: A, b: B) -> Result<(), ()> {
    match (a, b) {
        // arm 1
        (A::A1, B { field: true, .. }) => Ok(println!("A1 + B=T")),
        _ => Err(()),
    }
}

In this case we see again that Ok(..) are joined with the comma.


Edit: after a bit more of digging around the issues, I think #5521 might be related to the first issue I have, the trailing whitespaces.

Metadata

Metadata

Assignees

No one assigned

    Labels

    a-commentsa-matchesmatch arms, patterns, blocks, etce-trailing whitespaceerror[internal]: left behind trailing whitespace

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions