diff --git a/src/test/ui/for-loop-while/label_break_value.rs b/src/test/ui/for-loop-while/label_break_value.rs index 18930ac811e80..5776c0b1e0c77 100644 --- a/src/test/ui/for-loop-while/label_break_value.rs +++ b/src/test/ui/for-loop-while/label_break_value.rs @@ -95,6 +95,50 @@ fn label_break_mixed(v: u32) -> u32 { r } +fn label_break_match(c: u8, xe: u8, ye: i8) { + let mut x = 0; + let y = 'a: { + match c { + 0 => break 'a 0, + v if { if v % 2 == 0 { break 'a 1; }; v % 3 == 0 } => { x += 1; }, + v if { 'b: { break 'b v == 5; } } => { x = 41; }, + _ => 'b: { //~ WARNING `'b` shadows a label + break 'b (); + }, + } + x += 1; + -1 + }; + + assert_eq!(x, xe); + assert_eq!(y, ye); +} + +#[allow(unused_labels)] +fn label_break_macro() { + macro_rules! mac1 { + ($target:lifetime, $val:expr) => { + break $target $val; + }; + } + let x: u8 = 'a: { + 'b: { + mac1!('b, 1); + }; + 0 + }; + assert_eq!(x, 0); + let x: u8 = 'a: { //~ WARNING `'a` shadows a label + 'b: { //~ WARNING `'b` shadows a label + if true { + mac1!('a, 1); + } + }; + 0 + }; + assert_eq!(x, 1); +} + pub fn main() { assert_eq!(label_break(true, false), 1); assert_eq!(label_break(false, true), 2); @@ -112,5 +156,12 @@ pub fn main() { assert_eq!(label_break_mixed(5), 5); assert_eq!(label_break_mixed(6), 6); - // FIXME: ensure that labeled blocks work if produced by macros and in match arms + label_break_match(0, 0, 0); + label_break_match(1, 1, -1); + label_break_match(2, 0, 1); + label_break_match(3, 2, -1); + label_break_match(5, 42, -1); + label_break_match(7, 1, -1); + + label_break_macro(); } diff --git a/src/test/ui/for-loop-while/label_break_value.stderr b/src/test/ui/for-loop-while/label_break_value.stderr new file mode 100644 index 0000000000000..b1eb3204fd599 --- /dev/null +++ b/src/test/ui/for-loop-while/label_break_value.stderr @@ -0,0 +1,28 @@ +warning: label name `'b` shadows a label name that is already in scope + --> $DIR/label_break_value.rs:105:18 + | +LL | v if { 'b: { break 'b v == 5; } } => { x = 41; }, + | -- first declared here +LL | _ => 'b: { + | ^^ label `'b` already in scope + +warning: label name `'a` shadows a label name that is already in scope + --> $DIR/label_break_value.rs:131:17 + | +LL | let x: u8 = 'a: { + | -- first declared here +... +LL | let x: u8 = 'a: { + | ^^ label `'a` already in scope + +warning: label name `'b` shadows a label name that is already in scope + --> $DIR/label_break_value.rs:132:9 + | +LL | 'b: { + | -- first declared here +... +LL | 'b: { + | ^^ label `'b` already in scope + +warning: 3 warnings emitted + diff --git a/src/test/ui/for-loop-while/label_break_value_invalid.rs b/src/test/ui/for-loop-while/label_break_value_invalid.rs new file mode 100644 index 0000000000000..e603c8463b578 --- /dev/null +++ b/src/test/ui/for-loop-while/label_break_value_invalid.rs @@ -0,0 +1,39 @@ +#![crate_type = "lib"] +#![feature(label_break_value)] + +fn lbv_macro_test_hygiene_respected() { + macro_rules! mac2 { + ($val:expr) => { + break 'a $val; //~ ERROR undeclared label `'a` [E0426] + }; + } + let x: u8 = 'a: { + 'b: { + if true { + mac2!(2); + } + }; + 0 + }; + assert_eq!(x, 2); + + macro_rules! mac3 { + ($val:expr) => { + 'a: { + //~^ WARNING `'a` shadows a label + //~| WARNING `'a` shadows a label + //~| WARNING `'a` shadows a label + $val + } + }; + } + let x: u8 = mac3!('b: { //~ WARNING `'b` shadows a label + if true { + break 'a 3; //~ ERROR undeclared label `'a` [E0426] + } + 0 + }); + assert_eq!(x, 3); + let x: u8 = mac3!(break 'a 4); //~ ERROR undeclared label `'a` [E0426] + assert_eq!(x, 4); +} diff --git a/src/test/ui/for-loop-while/label_break_value_invalid.stderr b/src/test/ui/for-loop-while/label_break_value_invalid.stderr new file mode 100644 index 0000000000000..549b394e14b10 --- /dev/null +++ b/src/test/ui/for-loop-while/label_break_value_invalid.stderr @@ -0,0 +1,89 @@ +error[E0426]: use of undeclared label `'a` + --> $DIR/label_break_value_invalid.rs:7:19 + | +LL | break 'a $val; + | ^^ undeclared label `'a` +... +LL | mac2!(2); + | -------- in this macro invocation + | + = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0426]: use of undeclared label `'a` + --> $DIR/label_break_value_invalid.rs:32:19 + | +LL | let x: u8 = mac3!('b: { + | -- a label with a similar name is reachable +LL | if true { +LL | break 'a 3; + | ^^ + | | + | undeclared label `'a` + | help: try using similarly named label: `'b` + +error[E0426]: use of undeclared label `'a` + --> $DIR/label_break_value_invalid.rs:37:29 + | +LL | let x: u8 = mac3!(break 'a 4); + | ^^ undeclared label `'a` + +warning: label name `'a` shadows a label name that is already in scope + --> $DIR/label_break_value_invalid.rs:22:13 + | +LL | let x: u8 = 'a: { + | -- first declared here +... +LL | 'a: { + | ^^ label `'a` already in scope +... +LL | let x: u8 = mac3!('b: { + | _________________- +LL | | if true { +LL | | break 'a 3; +LL | | } +LL | | 0 +LL | | }); + | |______- in this macro invocation + | + = note: this warning originates in the macro `mac3` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: label name `'b` shadows a label name that is already in scope + --> $DIR/label_break_value_invalid.rs:30:23 + | +LL | 'b: { + | -- first declared here +... +LL | let x: u8 = mac3!('b: { + | ^^ label `'b` already in scope + +warning: label name `'a` shadows a label name that is already in scope + --> $DIR/label_break_value_invalid.rs:22:13 + | +LL | let x: u8 = 'a: { + | -- first declared here +... +LL | 'a: { + | ^^ label `'a` already in scope +... +LL | let x: u8 = mac3!(break 'a 4); + | ----------------- in this macro invocation + | + = note: this warning originates in the macro `mac3` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: label name `'a` shadows a label name that is already in scope + --> $DIR/label_break_value_invalid.rs:22:13 + | +LL | 'a: { + | ^^ + | | + | first declared here + | label `'a` already in scope +... +LL | let x: u8 = mac3!(break 'a 4); + | ----------------- in this macro invocation + | + = note: this warning originates in the macro `mac3` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors; 4 warnings emitted + +For more information about this error, try `rustc --explain E0426`.