about summary refs log tree commit diff
path: root/compiler/rustc_parse/src/parser/diagnostics.rs
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-03-19 16:52:56 +0100
committerGitHub <noreply@github.com>2025-03-19 16:52:56 +0100
commitc3f74bcb39849b10c8b336db18530c79d7cb8701 (patch)
treee50da18a5ccf7863256fc0f876ae75b55b7db1ee /compiler/rustc_parse/src/parser/diagnostics.rs
parent2df731d586319ec9a90676fcf7eca43ca60825c5 (diff)
parentf478853f425fc0207add653b48c49c937acaa94e (diff)
downloadrust-c3f74bcb39849b10c8b336db18530c79d7cb8701.tar.gz
rust-c3f74bcb39849b10c8b336db18530c79d7cb8701.zip
Rollup merge of #138589 - zachs18:block-label-not-supported-here-loop-body-help, r=petrochenkov
If a label is placed on the block of a loop instead of the header, suggest moving it to the header.

Fixes #138585

If a label is placed on the block of a loop instead of the header, suggest to the user moving it to the loop header instead of ~~suggesting to remove it~~ emitting a tool-only suggestion to remove it.

```rs
fn main() {
    loop 'a: { return; }
}
```

```diff
 error: block label not supported here
  --> src/main.rs:2:10
   |
 2 |     loop 'a: { return; }
   |          ^^^ not supported here
+  |
+help: if you meant to label the loop, move this label before the loop
+  |
+2 -     loop 'a: { return; }
+2 +     'a: loop { return; }
+  |
```

Questions for reviewer:

* The "desired output" in the linked issue had the main diagnostic be "misplaced loop label". Should the main diagnostic message the changed instead of leaving it as "block label not supported here"?
* Should this be `Applicability::MachineApplicable`?
Diffstat (limited to 'compiler/rustc_parse/src/parser/diagnostics.rs')
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs29
1 files changed, 23 insertions, 6 deletions
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 716ababb008..c1cca1186af 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -2874,7 +2874,12 @@ impl<'a> Parser<'a> {
         first_pat
     }
 
-    pub(crate) fn maybe_recover_unexpected_block_label(&mut self) -> bool {
+    /// If `loop_header` is `Some` and an unexpected block label is encountered,
+    /// it is suggested to be moved just before `loop_header`, else it is suggested to be removed.
+    pub(crate) fn maybe_recover_unexpected_block_label(
+        &mut self,
+        loop_header: Option<Span>,
+    ) -> bool {
         // Check for `'a : {`
         if !(self.check_lifetime()
             && self.look_ahead(1, |t| *t == token::Colon)
@@ -2885,16 +2890,28 @@ impl<'a> Parser<'a> {
         let label = self.eat_label().expect("just checked if a label exists");
         self.bump(); // eat `:`
         let span = label.ident.span.to(self.prev_token.span);
-        self.dcx()
+        let mut diag = self
+            .dcx()
             .struct_span_err(span, "block label not supported here")
-            .with_span_label(span, "not supported here")
-            .with_tool_only_span_suggestion(
+            .with_span_label(span, "not supported here");
+        if let Some(loop_header) = loop_header {
+            diag.multipart_suggestion(
+                "if you meant to label the loop, move this label before the loop",
+                vec![
+                    (label.ident.span.until(self.token.span), String::from("")),
+                    (loop_header.shrink_to_lo(), format!("{}: ", label.ident)),
+                ],
+                Applicability::MachineApplicable,
+            );
+        } else {
+            diag.tool_only_span_suggestion(
                 label.ident.span.until(self.token.span),
                 "remove this block label",
                 "",
                 Applicability::MachineApplicable,
-            )
-            .emit();
+            );
+        }
+        diag.emit();
         true
     }