diff --git a/src/test/compile-fail/loops-reject-duplicate-labels-2.rs b/src/test/compile-fail/loops-reject-duplicate-labels-2.rs new file mode 100644 index 0000000000000..db4cd1a21d1c1 --- /dev/null +++ b/src/test/compile-fail/loops-reject-duplicate-labels-2.rs @@ -0,0 +1,44 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength + +// Issue #21633: reject duplicate loop labels in function bodies. +// +// This is testing the generalization (to the whole function body) +// discussed here: +// http://internals.rust-lang.org/t/psa-rejecting-duplicate-loop-labels/1833 + +fn main() { + { 'fl: for _ in 0..10 { break; } } //~ NOTE shadowed label `'fl` declared here + { 'fl: loop { break; } } //~ ERROR label name `'fl` shadows a label name that is already in scope + + { 'lf: loop { break; } } //~ NOTE shadowed label `'lf` declared here + { 'lf: for _ in 0..10 { break; } } //~ ERROR label name `'lf` shadows a label name that is already in scope + + { 'wl: while 2 > 1 { break; } } //~ NOTE shadowed label `'wl` declared here + { 'wl: loop { break; } } //~ ERROR label name `'wl` shadows a label name that is already in scope + + { 'lw: loop { break; } } //~ NOTE shadowed label `'lw` declared here + { 'lw: while 2 > 1 { break; } } //~ ERROR label name `'lw` shadows a label name that is already in scope + + { 'fw: for _ in 0..10 { break; } } //~ NOTE shadowed label `'fw` declared here + { 'fw: while 2 > 1 { break; } } //~ ERROR label name `'fw` shadows a label name that is already in scope + + { 'wf: while 2 > 1 { break; } } //~ NOTE shadowed label `'wf` declared here + { 'wf: for _ in 0..10 { break; } } //~ ERROR label name `'wf` shadows a label name that is already in scope + + { 'tl: while let Some(_) = None:: { break; } } //~ NOTE shadowed label `'tl` declared here + { 'tl: loop { break; } } //~ ERROR label name `'tl` shadows a label name that is already in scope + + { 'lt: loop { break; } } //~ NOTE shadowed label `'lt` declared here + { 'lt: while let Some(_) = None:: { break; } } + //~^ ERROR label name `'lt` shadows a label name that is already in scope +} diff --git a/src/test/compile-fail/loops-reject-duplicate-labels.rs b/src/test/compile-fail/loops-reject-duplicate-labels.rs new file mode 100644 index 0000000000000..29c30d12f6bdc --- /dev/null +++ b/src/test/compile-fail/loops-reject-duplicate-labels.rs @@ -0,0 +1,50 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength + +// Issue #21633: reject duplicate loop labels in function bodies. +// This is testing the exact cases that are in the issue description. + +fn main() { + 'fl: for _ in 0..10 { break; } //~ NOTE shadowed label `'fl` declared here + 'fl: loop { break; } //~ ERROR label name `'fl` shadows a label name that is already in scope + + 'lf: loop { break; } //~ NOTE shadowed label `'lf` declared here + 'lf: for _ in 0..10 { break; } //~ ERROR label name `'lf` shadows a label name that is already in scope + + 'wl: while 2 > 1 { break; } //~ NOTE shadowed label `'wl` declared here + 'wl: loop { break; } //~ ERROR label name `'wl` shadows a label name that is already in scope + + 'lw: loop { break; } //~ NOTE shadowed label `'lw` declared here + 'lw: while 2 > 1 { break; } //~ ERROR label name `'lw` shadows a label name that is already in scope + + 'fw: for _ in 0..10 { break; } //~ NOTE shadowed label `'fw` declared here + 'fw: while 2 > 1 { break; } //~ ERROR label name `'fw` shadows a label name that is already in scope + + 'wf: while 2 > 1 { break; } //~ NOTE shadowed label `'wf` declared here + 'wf: for _ in 0..10 { break; } //~ ERROR label name `'wf` shadows a label name that is already in scope + + 'tl: while let Some(_) = None:: { break; } //~ NOTE shadowed label `'tl` declared here + 'tl: loop { break; } //~ ERROR label name `'tl` shadows a label name that is already in scope + + 'lt: loop { break; } //~ NOTE shadowed label `'lt` declared here + 'lt: while let Some(_) = None:: { break; } + //~^ ERROR label name `'lt` shadows a label name that is already in scope +} + +// Note however that it is okay for the same label to be reuse in +// different methods of one impl, as illustrated here. + +struct S; +impl S { + fn m1(&self) { 'okay: loop { break 'okay; } } + fn m2(&self) { 'okay: loop { break 'okay; } } +} diff --git a/src/test/compile-fail/loops-reject-labels-shadowing-lifetimes.rs b/src/test/compile-fail/loops-reject-labels-shadowing-lifetimes.rs new file mode 100644 index 0000000000000..c13d2629219cb --- /dev/null +++ b/src/test/compile-fail/loops-reject-labels-shadowing-lifetimes.rs @@ -0,0 +1,111 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Issue #21633: reject duplicate loop labels in function bodies. +// This is testing interaction between lifetime-params and labels. + +fn main() { + fn foo<'a>() { //~ NOTE shadowed lifetime `'a` declared here + 'a: loop { break 'a; } + //~^ ERROR label name `'a` shadows a lifetime name that is already in scope + } + + struct Struct<'b, 'c> { _f: &'b i8, _g: &'c i8 } + enum Enum<'d, 'e> { A(&'d i8), B(&'e i8) } + + impl<'d, 'e> Struct<'d, 'e> { + fn meth_okay() { + 'a: loop { break 'a; } + 'b: loop { break 'b; } + 'c: loop { break 'c; } + } + } + + impl <'d, 'e> Enum<'d, 'e> { + fn meth_okay() { + 'a: loop { break 'a; } + 'b: loop { break 'b; } + 'c: loop { break 'c; } + } + } + + impl<'bad, 'c> Struct<'bad, 'c> { //~ NOTE shadowed lifetime `'bad` declared here + fn meth_bad(&self) { + 'bad: loop { break 'bad; } + //~^ ERROR label name `'bad` shadows a lifetime name that is already in scope + } + } + + impl<'b, 'bad> Struct<'b, 'bad> { //~ NOTE shadowed lifetime `'bad` declared here + fn meth_bad2(&self) { + 'bad: loop { break 'bad; } + //~^ ERROR label name `'bad` shadows a lifetime name that is already in scope + } + } + + impl<'b, 'c> Struct<'b, 'c> { + fn meth_bad3<'bad>(x: &'bad i8) { //~ NOTE shadowed lifetime `'bad` declared here + 'bad: loop { break 'bad; } + //~^ ERROR label name `'bad` shadows a lifetime name that is already in scope + } + + fn meth_bad4<'a,'bad>(x: &'a i8, y: &'bad i8) { + //~^ NOTE shadowed lifetime `'bad` declared here + 'bad: loop { break 'bad; } + //~^ ERROR label name `'bad` shadows a lifetime name that is already in scope + } + } + + impl <'bad, 'e> Enum<'bad, 'e> { //~ NOTE shadowed lifetime `'bad` declared here + fn meth_bad(&self) { + 'bad: loop { break 'bad; } + //~^ ERROR label name `'bad` shadows a lifetime name that is already in scope + } + } + impl <'d, 'bad> Enum<'d, 'bad> { //~ NOTE shadowed lifetime `'bad` declared here + fn meth_bad2(&self) { + 'bad: loop { break 'bad; } + //~^ ERROR label name `'bad` shadows a lifetime name that is already in scope + } + } + impl <'d, 'e> Enum<'d, 'e> { + fn meth_bad3<'bad>(x: &'bad i8) { //~ NOTE shadowed lifetime `'bad` declared here + 'bad: loop { break 'bad; } + //~^ ERROR label name `'bad` shadows a lifetime name that is already in scope + } + + fn meth_bad4<'a,'bad>(x: &'bad i8) { //~ NOTE shadowed lifetime `'bad` declared here + 'bad: loop { break 'bad; } + //~^ ERROR label name `'bad` shadows a lifetime name that is already in scope + } + } + + trait HasDefaultMethod1<'bad> { //~ NOTE shadowed lifetime `'bad` declared here + fn meth_okay() { + 'c: loop { break 'c; } + } + fn meth_bad(&self) { + 'bad: loop { break 'bad; } + //~^ ERROR label name `'bad` shadows a lifetime name that is already in scope + } + } + trait HasDefaultMethod2<'a,'bad> { //~ NOTE shadowed lifetime `'bad` declared here + fn meth_bad(&self) { + 'bad: loop { break 'bad; } + //~^ ERROR label name `'bad` shadows a lifetime name that is already in scope + } + } + trait HasDefaultMethod3<'a,'b> { + fn meth_bad<'bad>(&self) { //~ NOTE shadowed lifetime `'bad` declared here + 'bad: loop { break 'bad; } + //~^ ERROR label name `'bad` shadows a lifetime name that is already in scope + } + } +} diff --git a/src/test/compile-fail/loops-reject-lifetime-shadowing-label.rs b/src/test/compile-fail/loops-reject-lifetime-shadowing-label.rs new file mode 100644 index 0000000000000..9b4498fbecadc --- /dev/null +++ b/src/test/compile-fail/loops-reject-lifetime-shadowing-label.rs @@ -0,0 +1,32 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Issue #21633: reject duplicate loop labels in function bodies. +// +// Test rejection of lifetimes in *expressions* that shadow loop labels. + +fn main() { + // Reusing lifetime `'a` in function item is okay. + fn foo<'a>(x: &'a i8) -> i8 { *x } + + // So is reusing `'a` in struct item + struct S1<'a> { x: &'a i8 } impl<'a> S1<'a> { fn m(&self) {} } + // and a method item + struct S2; impl S2 { fn m<'a>(&self) {} } + + let z = 3_i8; + + 'a: loop { //~ NOTE shadowed label `'a` declared here + let b = Box::new(|x: i8| *x) as Box Fn(&'a i8)>; + //~^ ERROR lifetime name `'a` shadows a label name that is already in scope + assert_eq!((*b)(&z), z); + break 'a; + } +}