about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-08-04 07:17:25 +0000
committerbors <bors@rust-lang.org>2021-08-04 07:17:25 +0000
commit49ca3d9796030fc0a85089460e9f825ceecc08ed (patch)
treec2c0348ec5549e1e143498e37078e120e273fb6e /src
parent71ff9b41e9ebd3e336019513917a7a8868d1cc66 (diff)
parent7c81132a60579de56bd4baa7866fa9db2ecd5ddd (diff)
downloadrust-49ca3d9796030fc0a85089460e9f825ceecc08ed.tar.gz
rust-49ca3d9796030fc0a85089460e9f825ceecc08ed.zip
Auto merge of #87026 - FabianWolff:issue-86948, r=estebank
Allow labeled loops as value expressions for `break`

Fixes #86948. This is currently allowed:
```rust
return 'label: loop { break 'label 42; };
break ('label: loop { break 'label 42; });
break 1 + 'label: loop { break 'label 42; };
break 'outer 'inner: loop { break 'inner 42; };
```
But not this:
```rust
break 'label: loop { break 'label 42; };
```
I have fixed this, so that the above now parses as an unlabeled break with a labeled loop as its value expression.
Diffstat (limited to 'src')
-rw-r--r--src/test/ui/parser/lifetime_starts_expressions.rs32
-rw-r--r--src/test/ui/parser/lifetime_starts_expressions.stderr52
2 files changed, 67 insertions, 17 deletions
diff --git a/src/test/ui/parser/lifetime_starts_expressions.rs b/src/test/ui/parser/lifetime_starts_expressions.rs
index e0098793e1f..903b4de6ef4 100644
--- a/src/test/ui/parser/lifetime_starts_expressions.rs
+++ b/src/test/ui/parser/lifetime_starts_expressions.rs
@@ -1,13 +1,39 @@
+#![allow(unused, dead_code)]
+
 fn foo() -> u32 {
     return 'label: loop { break 'label 42; };
 }
 
 fn bar() -> u32 {
     loop { break 'label: loop { break 'label 42; }; }
-    //~^ ERROR expected identifier, found keyword `loop`
-    //~| ERROR expected type, found keyword `loop`
+    //~^ ERROR: parentheses are required around this expression to avoid confusion
+    //~| HELP: wrap the expression in parentheses
+}
+
+fn baz() -> u32 {
+    'label: loop {
+        break 'label
+        //~^ WARNING: this labeled break expression is easy to confuse with an unlabeled break
+            loop { break 42; };
+            //~^ HELP: wrap this expression in parentheses
+    };
+
+    'label2: loop {
+        break 'label2 'inner: loop { break 42; };
+        // no warnings or errors here
+    }
 }
 
 pub fn main() {
-    foo();
+    // Regression test for issue #86948, as resolved in #87026:
+    let a = 'first_loop: loop {
+        break 'first_loop 1;
+    };
+    let b = loop {
+        break 'inner_loop: loop {
+        //~^ ERROR: parentheses are required around this expression to avoid confusion
+        //~| HELP: wrap the expression in parentheses
+            break 'inner_loop 1;
+        };
+    };
 }
diff --git a/src/test/ui/parser/lifetime_starts_expressions.stderr b/src/test/ui/parser/lifetime_starts_expressions.stderr
index 7275841ebb8..6f3320e283c 100644
--- a/src/test/ui/parser/lifetime_starts_expressions.stderr
+++ b/src/test/ui/parser/lifetime_starts_expressions.stderr
@@ -1,23 +1,47 @@
-error: expected identifier, found keyword `loop`
-  --> $DIR/lifetime_starts_expressions.rs:6:26
+error: parentheses are required around this expression to avoid confusion with a labeled break expression
+  --> $DIR/lifetime_starts_expressions.rs:8:18
    |
 LL |     loop { break 'label: loop { break 'label 42; }; }
-   |                          ^^^^ expected identifier, found keyword
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: you can escape reserved keywords to use them as identifiers
+help: wrap the expression in parentheses
    |
-LL |     loop { break 'label: r#loop { break 'label 42; }; }
-   |                          ^^^^^^
+LL |     loop { break ('label: loop { break 'label 42; }); }
+   |                  ^                                 ^
 
-error: expected type, found keyword `loop`
-  --> $DIR/lifetime_starts_expressions.rs:6:26
+error: parentheses are required around this expression to avoid confusion with a labeled break expression
+  --> $DIR/lifetime_starts_expressions.rs:33:15
    |
-LL |     loop { break 'label: loop { break 'label 42; }; }
-   |                        - ^^^^ expected type
-   |                        |
-   |                        help: maybe write a path separator here: `::`
+LL |           break 'inner_loop: loop {
+   |  _______________^
+LL | |
+LL | |
+LL | |             break 'inner_loop 1;
+LL | |         };
+   | |_________^
+   |
+help: wrap the expression in parentheses
+   |
+LL |         break ('inner_loop: loop {
+LL |
+LL |
+LL |             break 'inner_loop 1;
+LL |         });
+   |
+
+warning: this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression
+  --> $DIR/lifetime_starts_expressions.rs:15:9
+   |
+LL | /         break 'label
+LL | |
+LL | |             loop { break 42; };
+   | |______________________________^
+   |
+   = note: `#[warn(break_with_label_and_loop)]` on by default
+help: wrap this expression in parentheses
    |
-   = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
+LL |             (loop { break 42; });
+   |             ^                  ^
 
-error: aborting due to 2 previous errors
+error: aborting due to 2 previous errors; 1 warning emitted