Repository: rust-lang/rustfmt (rust)

Issue:
Non-idempotent rustfmt run, adding commas to comments
Consider this (minimized) code:
```rust
struct Tau {}
impl Tau where (): Clone //,
{
}
```

Every time you run `rustfmt foo.rs`, it adds another comma to that comment.

```console
$ cat foo.rs
struct Tau {}
impl Tau where (): Clone //,
{
}

$ for i in $(seq 1 10); do rustfmt foo.rs; wc -c foo.rs; done
48 foo.rs
49 foo.rs
50 foo.rs
51 foo.rs
52 foo.rs
53 foo.rs
54 foo.rs
55 foo.rs
56 foo.rs
57 foo.rs

$ cat foo.rs
struct Tau {}
impl Tau where (): Clone //,,,,,,,,,,,
{
}
```

Tested on multiple versions:
+ rustfmt 1.5.2-stable (eb26296 2023-08-03)
+ rustfmt 1.5.2-stable (90c54180 2023-05-31)

Pull request description:
Fixes comma added to comment in where-clause
Fixes #5941

The issue was caused by the trailing comment handling for where-clauses. For this particular issue, the problem was that we added a trailing comma if our where-clause's last line had a single line comment. Then we proceeded to add a comma to said single line comment.


Patch:
diff --git a/src/items.rs b/src/items.rs
index edb5a5b6..d6488ffd 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -831,13 +831,15 @@ pub(crate) fn format_impl(
 
     if is_impl_single_line(context, items.as_slice(), &result, &where_clause_str, item)? {
         result.push_str(&where_clause_str);
-        if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) {
-            // if the where_clause contains extra comments AND
-            // there is only one where-clause predicate
-            // recover the suppressed comma in single line where_clause formatting
+        if where_clause_str.contains('\n') {
+            // If there is only one where-clause predicate
+            // and the where-clause spans multiple lines,
+            // then recover the suppressed comma in single line where-clause formatting
             if generics.where_clause.predicates.len() == 1 {
                 result.push(',');
             }
+        }
+        if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) {
             result.push_str(&format!("{sep}{{{sep}}}"));
         } else {
             result.push_str(" {}");


Test patch:
diff --git a/tests/target/impl.rs b/tests/target/impl.rs
index f37fbcf1..10de0ecd 100644
--- a/tests/target/impl.rs
+++ b/tests/target/impl.rs
@@ -32,6 +32,11 @@ where
 {
 }
 
+// #5941
+impl T where (): Clone // Should not add comma to comment
+{
+}
+
 // #1823
 default impl Trait for X {}
 default unsafe impl Trait for Y {}