Repository: rust-lang/rustfmt (rust)

Issue:
Incorrectly strips r# prefix from labels
Rust playground: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=051766b3584e787d3abab1d2f18424bb

The following code:

```rust
'r#if: {
  break 'r#if;
}
```

when run through either stable or nightly rustfmt will incorrectly be formatted into this:

```rust
'r#if: {
  break 'if;
}
```

which rustc will complain because `'if` is an invalid label name:

```rust
error: invalid label name `'if`
 --> src/main.rs:5:15
  |
5 |         break 'if;
  |               ^^^
```

Note that this still does occur if the label name is not a keyword:

```rust
'r#a: {
  break 'r#a;
}
```

is formatted into

```rust
'r#a: {
  break 'a;
}
```

However this does not cause an error.

Versions of `rustfmt` (from rust-playground)
```1.8.0-stable (2024-11-26 90b35a6239)```
and
```1.8.0-nightly (2024-11-30 7442931d49)```

<!-- TRIAGEBOT_START -->

<!-- TRIAGEBOT_ASSIGN_START -->

<!-- TRIAGEBOT_ASSIGN_DATA_START$${"user":"sobatha"}$$TRIAGEBOT_ASSIGN_DATA_END -->

<!-- TRIAGEBOT_ASSIGN_END -->
<!-- TRIAGEBOT_END -->

Pull request description:
Fix incorrect strip r# prefix from labels
This PR fix #6411 

This PR fixes an issue where rustfmt incorrectly removes the r# prefix in raw labels(introduced in 1.83 https://github.com/rust-lang/rust/pull/126452), causing invalid label names like 'if instead of 'r#if. 

Patch:
diff --git a/src/expr.rs b/src/expr.rs
index 068af184..0751d65a 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -200,14 +200,22 @@ pub(crate) fn format_expr(
         }
         ast::ExprKind::Continue(ref opt_label) => {
             let id_str = match *opt_label {
-                Some(label) => format!(" {}", label.ident),
+                Some(label) => {
+                    // Ident lose the `r#` prefix in raw labels,　so use the original snippet
+                    let label_name = context.snippet(label.ident.span);
+                    format!(" {}", label_name)
+                }
                 None => String::new(),
             };
             Ok(format!("continue{id_str}"))
         }
         ast::ExprKind::Break(ref opt_label, ref opt_expr) => {
             let id_str = match *opt_label {
-                Some(label) => format!(" {}", label.ident),
+                Some(label) => {
+                    // Ident lose the `r#` prefix in raw labels,　so use the original snippet
+                    let label_name = context.snippet(label.ident.span);
+                    format!(" {}", label_name)
+                }
                 None => String::new(),
             };
 


Test patch:
diff --git a/tests/target/issue-6411.rs b/tests/target/issue-6411.rs
new file mode 100644
index 00000000..a1166a74
--- /dev/null
+++ b/tests/target/issue-6411.rs
@@ -0,0 +1,21 @@
+// rustfmt-edition: 2021
+
+fn test_break() {
+    'r#if: {
+        break 'r#if;
+    }
+
+    'r#a: {
+        break 'r#a;
+    }
+}
+
+fn test_continue() {
+    'r#if: {
+        continue 'r#if;
+    }
+
+    'r#a: {
+        continue 'r#a;
+    }
+}