about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs17
-rw-r--r--src/test/ui/parser/labeled-no-colon-expr.stderr6
-rw-r--r--src/test/ui/parser/recover-labeled-non-block-expr.fixed7
-rw-r--r--src/test/ui/parser/recover-labeled-non-block-expr.rs7
-rw-r--r--src/test/ui/parser/recover-labeled-non-block-expr.stderr43
5 files changed, 67 insertions, 13 deletions
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 0d252c3d465..0bc71de90ff 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1557,6 +1557,8 @@ impl<'a> Parser<'a> {
 
             // Continue as an expression in an effort to recover on `'label: non_block_expr`.
             let expr = self.parse_expr().map(|expr| {
+                let span = expr.span;
+
                 let found_labeled_breaks = {
                     struct FindLabeledBreaksVisitor(bool);
 
@@ -1573,13 +1575,22 @@ impl<'a> Parser<'a> {
                     vis.0
                 };
 
-                // Suggestion involves adding a (as of time of writing this, unstable) labeled block
-                // so if the label is not used, just return the unmodified expression
+                // Suggestion involves adding a (as of time of writing this, unstable) labeled block.
+                //
+                // If there are no breaks that may use this label, suggest removing the label and
+                // recover to the unmodified expression.
                 if !found_labeled_breaks {
+                    let msg = "consider removing the label";
+                    err.span_suggestion_verbose(
+                        lo.until(span),
+                        msg,
+                        "",
+                        Applicability::MachineApplicable,
+                    );
+
                     return expr;
                 }
 
-                let span = expr.span;
                 let sugg_msg = "consider enclosing expression in a block";
                 let suggestions = vec![
                     (span.shrink_to_lo(), "{".to_owned()),
diff --git a/src/test/ui/parser/labeled-no-colon-expr.stderr b/src/test/ui/parser/labeled-no-colon-expr.stderr
index 26884dc5d74..5c9597c440c 100644
--- a/src/test/ui/parser/labeled-no-colon-expr.stderr
+++ b/src/test/ui/parser/labeled-no-colon-expr.stderr
@@ -47,6 +47,12 @@ error: expected `while`, `for`, `loop` or `{` after a label
    |
 LL |     'l4 0;
    |         ^ expected `while`, `for`, `loop` or `{` after a label
+   |
+help: consider removing the label
+   |
+LL -     'l4 0;
+LL +     0;
+   | 
 
 error: labeled expression must be followed by `:`
   --> $DIR/labeled-no-colon-expr.rs:8:9
diff --git a/src/test/ui/parser/recover-labeled-non-block-expr.fixed b/src/test/ui/parser/recover-labeled-non-block-expr.fixed
index aabda4a67a1..3193d90d2d3 100644
--- a/src/test/ui/parser/recover-labeled-non-block-expr.fixed
+++ b/src/test/ui/parser/recover-labeled-non-block-expr.fixed
@@ -1,11 +1,12 @@
 // run-rustfix
 #![feature(label_break_value)]
 fn main() {
-    // FIXME(waffle): add this back
-    // #[allow(unused_labels)]
-    // 'label: 1 + 1; // ERROR expected `while`, `for`, `loop` or `{` after a label
+    let _ = 1 + 1; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
 
+    match () { () => {}, }; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
     'label: {match () { () => break 'label, }}; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
+    #[allow(unused_labels)]
+    'label: {match () { () => 'lp: loop { break 'lp 0 }, }}; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
 
     let x = 1;
     let _i = 'label: {match x { //~ ERROR expected `while`, `for`, `loop` or `{` after a label
diff --git a/src/test/ui/parser/recover-labeled-non-block-expr.rs b/src/test/ui/parser/recover-labeled-non-block-expr.rs
index 9244acabc26..35862e2eef9 100644
--- a/src/test/ui/parser/recover-labeled-non-block-expr.rs
+++ b/src/test/ui/parser/recover-labeled-non-block-expr.rs
@@ -1,11 +1,12 @@
 // run-rustfix
 #![feature(label_break_value)]
 fn main() {
-    // FIXME(waffle): add this back
-    // #[allow(unused_labels)]
-    // 'label: 1 + 1; // ERROR expected `while`, `for`, `loop` or `{` after a label
+    let _ = 'label: 1 + 1; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
 
+    'label: match () { () => {}, }; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
     'label: match () { () => break 'label, }; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
+    #[allow(unused_labels)]
+    'label: match () { () => 'lp: loop { break 'lp 0 }, }; //~ ERROR expected `while`, `for`, `loop` or `{` after a label
 
     let x = 1;
     let _i = 'label: match x { //~ ERROR expected `while`, `for`, `loop` or `{` after a label
diff --git a/src/test/ui/parser/recover-labeled-non-block-expr.stderr b/src/test/ui/parser/recover-labeled-non-block-expr.stderr
index 37843141ef3..e289c5db5cb 100644
--- a/src/test/ui/parser/recover-labeled-non-block-expr.stderr
+++ b/src/test/ui/parser/recover-labeled-non-block-expr.stderr
@@ -1,5 +1,29 @@
 error: expected `while`, `for`, `loop` or `{` after a label
-  --> $DIR/recover-labeled-non-block-expr.rs:8:13
+  --> $DIR/recover-labeled-non-block-expr.rs:4:21
+   |
+LL |     let _ = 'label: 1 + 1;
+   |                     ^ expected `while`, `for`, `loop` or `{` after a label
+   |
+help: consider removing the label
+   |
+LL -     let _ = 'label: 1 + 1;
+LL +     let _ = 1 + 1;
+   | 
+
+error: expected `while`, `for`, `loop` or `{` after a label
+  --> $DIR/recover-labeled-non-block-expr.rs:6:13
+   |
+LL |     'label: match () { () => {}, };
+   |             ^^^^^ expected `while`, `for`, `loop` or `{` after a label
+   |
+help: consider removing the label
+   |
+LL -     'label: match () { () => {}, };
+LL +     match () { () => {}, };
+   | 
+
+error: expected `while`, `for`, `loop` or `{` after a label
+  --> $DIR/recover-labeled-non-block-expr.rs:7:13
    |
 LL |     'label: match () { () => break 'label, };
    |             ^^^^^ expected `while`, `for`, `loop` or `{` after a label
@@ -10,7 +34,18 @@ LL |     'label: {match () { () => break 'label, }};
    |             +                                +
 
 error: expected `while`, `for`, `loop` or `{` after a label
-  --> $DIR/recover-labeled-non-block-expr.rs:11:22
+  --> $DIR/recover-labeled-non-block-expr.rs:9:13
+   |
+LL |     'label: match () { () => 'lp: loop { break 'lp 0 }, };
+   |             ^^^^^ expected `while`, `for`, `loop` or `{` after a label
+   |
+help: consider enclosing expression in a block
+   |
+LL |     'label: {match () { () => 'lp: loop { break 'lp 0 }, }};
+   |             +                                             +
+
+error: expected `while`, `for`, `loop` or `{` after a label
+  --> $DIR/recover-labeled-non-block-expr.rs:12:22
    |
 LL |     let _i = 'label: match x {
    |                      ^^^^^ expected `while`, `for`, `loop` or `{` after a label
@@ -26,7 +61,7 @@ LL |                 break 'label 13
  ...
 
 error: expected `while`, `for`, `loop` or `{` after a label
-  --> $DIR/recover-labeled-non-block-expr.rs:25:24
+  --> $DIR/recover-labeled-non-block-expr.rs:26:24
    |
 LL |     let _val = 'label: (1, if other == 3 { break 'label (2, 3) } else { other });
    |                        ^ expected `while`, `for`, `loop` or `{` after a label
@@ -36,5 +71,5 @@ help: consider enclosing expression in a block
 LL |     let _val = 'label: {(1, if other == 3 { break 'label (2, 3) } else { other })};
    |                        +                                                         +
 
-error: aborting due to 3 previous errors
+error: aborting due to 6 previous errors