Repository: rust-lang/rustfmt (rust)

Issue:
rustfmt stops working if the comment just after the => of a "match" contains "=>"
Hello,

I've noticed that rustfmt stops working if the comment just after the => of a "match" contains "=>".

info :
rustfmt 1.7.0-stable (82e1608 2023-12-21)
rustc 1.75.0 (82e1608df 2023-12-21)


here's an example code :
```rust
fn main() {
    let a = 50u32;
    match a {
        10 =>
        // comment => 10
                {
            println!("A")
        }
        20 => {
                            println!("B")
        }
        _ => {
            println!("C")
        }
    }
}
```

the problem is in the comment :
`// comment => 10`

the comment contains the symbol "=>", if you try to use rustfmt it won't work.
but if you delete the "=>" from the comment, or simply add a space like this "= >", rustmt works again.

you can test the bug here :  ( click on the top-right "Tools -> Rustfmt" button to start formatting, but it won't work as long as the comment contains "=>" )
[Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=41d70dfff0c31abd78d5cbe156481439)

Thank you for the wonderful work that you do :+1: 






Pull request:
Fix failure with `=>` in comment after match `=>`
Fixes #5998 

## Background
(1) Comment without arrow `=>`
```rust
fn main() {
    match a {
        _ =>
        // comment with ==
                {
            println!("A")
        }
    }
}
```
(2) Comment without arrow `=>`
```rust
fn main() {
    match a {
        _ =>
        // comment with =>
                {
            println!("A")
        }
    }
}
```
Previously, second example fails to reformat unlike the first example. The cause was rustfmt returns original code snippet when comment is lost after rewrite. When `rewrite_match_body`, there's logic to check if comment exists between `=>` and match body, but it tries to find another `=>` in arrow_snippet considering the case with nested match. Since `=>` in comment was also caught with `rfind()`, the comment was lost, which led to silent failure. 

## Solution
Add extra check whether found `=>` was included in single line comment.

## TODO
- [ ] add more test case and verify
- [ ] think for any other alternative approach

Patch:
diff --git a/src/matches.rs b/src/matches.rs
index 5e36d9e8..06e7078b 100644
--- a/src/matches.rs
+++ b/src/matches.rs
@@ -5,7 +5,7 @@ use std::iter::repeat;
 use rustc_ast::{ast, ptr};
 use rustc_span::{BytePos, Span};
 
-use crate::comment::{combine_strs_with_missing_comments, rewrite_comment};
+use crate::comment::{combine_strs_with_missing_comments, rewrite_comment, FindUncommented};
 use crate::config::lists::*;
 use crate::config::{Config, ControlBraceStyle, IndentStyle, MatchArmLeadingPipe, Version};
 use crate::expr::{
@@ -402,7 +402,11 @@ fn rewrite_match_body(
         let arrow_snippet = context.snippet(arrow_span).trim();
         // search for the arrow starting from the end of the snippet since there may be a match
         // expression within the guard
-        let arrow_index = arrow_snippet.rfind("=>").unwrap();
+        let arrow_index = if context.config.version() == Version::One {
+            arrow_snippet.rfind("=>").unwrap()
+        } else {
+            arrow_snippet.find_last_uncommented("=>").unwrap()
+        };
         // 2 = `=>`
         let comment_str = arrow_snippet[arrow_index + 2..].trim();
         if comment_str.is_empty() {


Test patch:
diff --git a/tests/source/arrow_in_comments/arrow_in_single_comment.rs b/tests/source/arrow_in_comments/arrow_in_single_comment.rs
new file mode 100644
index 00000000..fb0576a4
--- /dev/null
+++ b/tests/source/arrow_in_comments/arrow_in_single_comment.rs
@@ -0,0 +1,10 @@
+// rustfmt-version: Two
+fn main() {
+    match a {
+        _ =>
+        // comment with =>
+                {
+            println!("A")
+        }
+    }
+}
diff --git a/tests/source/arrow_in_comments/multiple_arrows.rs b/tests/source/arrow_in_comments/multiple_arrows.rs
new file mode 100644
index 00000000..fc696b30
--- /dev/null
+++ b/tests/source/arrow_in_comments/multiple_arrows.rs
@@ -0,0 +1,14 @@
+// rustfmt-version: Two
+fn main() {
+    match a {
+        _ => // comment with => 
+        match b {
+            // one goes to =>
+            one => {
+                println("1");
+            }
+            // two goes to =>
+            two => { println("2"); }
+        } 
+    }
+}
diff --git a/tests/target/arrow_in_comments/arrow_in_single_comment.rs b/tests/target/arrow_in_comments/arrow_in_single_comment.rs
new file mode 100644
index 00000000..deffdbee
--- /dev/null
+++ b/tests/target/arrow_in_comments/arrow_in_single_comment.rs
@@ -0,0 +1,10 @@
+// rustfmt-version: Two
+fn main() {
+    match a {
+        _ =>
+        // comment with =>
+        {
+            println!("A")
+        }
+    }
+}
diff --git a/tests/target/arrow_in_comments/multiple_arrows.rs b/tests/target/arrow_in_comments/multiple_arrows.rs
new file mode 100644
index 00000000..b0443411
--- /dev/null
+++ b/tests/target/arrow_in_comments/multiple_arrows.rs
@@ -0,0 +1,19 @@
+// rustfmt-version: Two
+fn main() {
+    match a {
+        _ =>
+        // comment with =>
+        {
+            match b {
+                // one goes to =>
+                one => {
+                    println("1");
+                }
+                // two goes to =>
+                two => {
+                    println("2");
+                }
+            }
+        }
+    }
+}