diff options
| author | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2019-07-27 01:33:01 +0300 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2019-07-27 18:56:16 +0300 |
| commit | 9be35f82c1abf2ecbab489bca9eca138ea648312 (patch) | |
| tree | 69888506e34af447d9748c0d542de3ba1dd76210 /src/test/ui/for-loop-while | |
| parent | ca9faa52f5ada0054b1fa27d97aedf448afb059b (diff) | |
| download | rust-9be35f82c1abf2ecbab489bca9eca138ea648312.tar.gz rust-9be35f82c1abf2ecbab489bca9eca138ea648312.zip | |
tests: Move run-pass tests without naming conflicts to ui
Diffstat (limited to 'src/test/ui/for-loop-while')
44 files changed, 959 insertions, 0 deletions
diff --git a/src/test/ui/for-loop-while/auto-loop.rs b/src/test/ui/for-loop-while/auto-loop.rs new file mode 100644 index 00000000000..f02ac43c734 --- /dev/null +++ b/src/test/ui/for-loop-while/auto-loop.rs @@ -0,0 +1,10 @@ +// run-pass + +pub fn main() { + let mut sum = 0; + let xs = vec![1, 2, 3, 4, 5]; + for x in &xs { + sum += *x; + } + assert_eq!(sum, 15); +} diff --git a/src/test/ui/for-loop-while/break-value.rs b/src/test/ui/for-loop-while/break-value.rs new file mode 100644 index 00000000000..9fc49fa8181 --- /dev/null +++ b/src/test/ui/for-loop-while/break-value.rs @@ -0,0 +1,7 @@ +// run-pass +#![allow(unreachable_code)] +// pretty-expanded FIXME #23616 + +fn int_id(x: isize) -> isize { return x; } + +pub fn main() { loop { int_id(break); } } diff --git a/src/test/ui/for-loop-while/break.rs b/src/test/ui/for-loop-while/break.rs new file mode 100644 index 00000000000..427b1b7a063 --- /dev/null +++ b/src/test/ui/for-loop-while/break.rs @@ -0,0 +1,25 @@ +// run-pass + +pub fn main() { + let mut i = 0; + while i < 20 { i += 1; if i == 10 { break; } } + assert_eq!(i, 10); + loop { i += 1; if i == 20 { break; } } + assert_eq!(i, 20); + let xs = [1, 2, 3, 4, 5, 6]; + for x in &xs { + if *x == 3 { break; } assert!((*x <= 3)); + } + i = 0; + while i < 10 { i += 1; if i % 2 == 0 { continue; } assert!((i % 2 != 0)); } + i = 0; + loop { + i += 1; if i % 2 == 0 { continue; } assert!((i % 2 != 0)); + if i >= 10 { break; } + } + let ys = vec![1, 2, 3, 4, 5, 6]; + for x in &ys { + if *x % 2 == 0 { continue; } + assert!((*x % 2 != 0)); + } +} diff --git a/src/test/ui/for-loop-while/for-destruct.rs b/src/test/ui/for-loop-while/for-destruct.rs new file mode 100644 index 00000000000..7ca8d4ded25 --- /dev/null +++ b/src/test/ui/for-loop-while/for-destruct.rs @@ -0,0 +1,9 @@ +// run-pass + +struct Pair { x: isize, y: isize } + +pub fn main() { + for elt in &(vec![Pair {x: 10, y: 20}, Pair {x: 30, y: 0}]) { + assert_eq!(elt.x + elt.y, 30); + } +} diff --git a/src/test/ui/for-loop-while/for-loop-goofiness.rs b/src/test/ui/for-loop-while/for-loop-goofiness.rs new file mode 100644 index 00000000000..872ab168bb2 --- /dev/null +++ b/src/test/ui/for-loop-while/for-loop-goofiness.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(dead_code)] + +enum BogusOption<T> { + None, + Some(T), +} + +type Iterator = isize; + +pub fn main() { + let x = [ 3, 3, 3 ]; + for i in &x { + assert_eq!(*i, 3); + } +} diff --git a/src/test/ui/for-loop-while/for-loop-has-unit-body.rs b/src/test/ui/for-loop-while/for-loop-has-unit-body.rs new file mode 100644 index 00000000000..38c34d2dc2e --- /dev/null +++ b/src/test/ui/for-loop-while/for-loop-has-unit-body.rs @@ -0,0 +1,13 @@ +// run-pass +fn main() { + // Check that the tail statement in the body unifies with something + for _ in 0..3 { + #[allow(deprecated)] + unsafe { std::mem::uninitialized() } + } + + // Check that the tail statement in the body can be unit + for _ in 0..3 { + () + } +} diff --git a/src/test/ui/for-loop-while/for-loop-into-iterator.rs b/src/test/ui/for-loop-while/for-loop-into-iterator.rs new file mode 100644 index 00000000000..199d4ddb299 --- /dev/null +++ b/src/test/ui/for-loop-while/for-loop-into-iterator.rs @@ -0,0 +1,19 @@ +// run-pass +// Test that for loops can do what RFC #235 claims + + +fn main() { + let mut v = vec![1]; + + for x in &v { + assert_eq!(x, &1); + } + + for x in &mut v { + assert_eq!(x, &mut 1); + } + + for x in v { + assert_eq!(x, 1); + } +} diff --git a/src/test/ui/for-loop-while/for-loop-lifetime-of-unbound-values.rs b/src/test/ui/for-loop-while/for-loop-lifetime-of-unbound-values.rs new file mode 100644 index 00000000000..6a38764a131 --- /dev/null +++ b/src/test/ui/for-loop-while/for-loop-lifetime-of-unbound-values.rs @@ -0,0 +1,34 @@ +// run-pass +// Test when destructors run in a for loop. The intention is +// that the value for each iteration is dropped *after* the loop +// body has executed. This is true even when the value is assigned +// to a `_` pattern (and hence ignored). + +use std::cell::Cell; + +struct Flag<'a>(&'a Cell<bool>); + +impl<'a> Drop for Flag<'a> { + fn drop(&mut self) { + self.0.set(false) + } +} + +fn main() { + let alive2 = Cell::new(true); + for _i in std::iter::once(Flag(&alive2)) { + // The Flag value should be alive in the for loop body + assert_eq!(alive2.get(), true); + } + // The Flag value should be dead outside of the loop + assert_eq!(alive2.get(), false); + + let alive = Cell::new(true); + for _ in std::iter::once(Flag(&alive)) { + // The Flag value should be alive in the for loop body even if it wasn't + // bound by the for loop + assert_eq!(alive.get(), true); + } + // The Flag value should be dead outside of the loop + assert_eq!(alive.get(), false); +} diff --git a/src/test/ui/for-loop-while/for-loop-macro.rs b/src/test/ui/for-loop-while/for-loop-macro.rs new file mode 100644 index 00000000000..5abccd2a141 --- /dev/null +++ b/src/test/ui/for-loop-while/for-loop-macro.rs @@ -0,0 +1,11 @@ +// run-pass +macro_rules! var { + ( $name:ident ) => ( $name ); +} + +pub fn main() { + let x = [ 3, 3, 3 ]; + for var!(i) in &x { + assert_eq!(*i, 3); + } +} diff --git a/src/test/ui/for-loop-while/for-loop-mut-ref-element.rs b/src/test/ui/for-loop-while/for-loop-mut-ref-element.rs new file mode 100644 index 00000000000..a3d82ace9e2 --- /dev/null +++ b/src/test/ui/for-loop-while/for-loop-mut-ref-element.rs @@ -0,0 +1,6 @@ +// run-pass +// Tests that for loops can bind elements as mutable references + +fn main() { + for ref mut _a in std::iter::once(true) {} +} diff --git a/src/test/ui/for-loop-while/for-loop-no-std.rs b/src/test/ui/for-loop-while/for-loop-no-std.rs new file mode 100644 index 00000000000..65a33c5f16f --- /dev/null +++ b/src/test/ui/for-loop-while/for-loop-no-std.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(unused_imports)] +#![feature(lang_items, start)] +#![no_std] + +extern crate std as other; + +#[macro_use] extern crate alloc; + +#[start] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + for _ in [1,2,3].iter() { } + 0 +} diff --git a/src/test/ui/for-loop-while/for-loop-panic.rs b/src/test/ui/for-loop-while/for-loop-panic.rs new file mode 100644 index 00000000000..ac607d6d731 --- /dev/null +++ b/src/test/ui/for-loop-while/for-loop-panic.rs @@ -0,0 +1,4 @@ +// run-pass + + +pub fn main() { let x: Vec<isize> = Vec::new(); for _ in &x { panic!("moop"); } } diff --git a/src/test/ui/for-loop-while/for-loop-unconstrained-element-type-i32-fallback.rs b/src/test/ui/for-loop-while/for-loop-unconstrained-element-type-i32-fallback.rs new file mode 100644 index 00000000000..a1e9b1ed87d --- /dev/null +++ b/src/test/ui/for-loop-while/for-loop-unconstrained-element-type-i32-fallback.rs @@ -0,0 +1,11 @@ +// run-pass +// Test that the type of `sum` falls back to `i32` here, +// and that the for loop desugaring doesn't interfere with +// that. + +fn main() { + let mut sum = 0; + for i in Vec::new() { + sum += &i; + } +} diff --git a/src/test/ui/for-loop-while/foreach-external-iterators-break.rs b/src/test/ui/for-loop-while/foreach-external-iterators-break.rs new file mode 100644 index 00000000000..7de6a4f8acb --- /dev/null +++ b/src/test/ui/for-loop-while/foreach-external-iterators-break.rs @@ -0,0 +1,13 @@ +// run-pass + +pub fn main() { + let x = [1; 100]; + let mut y = 0; + for i in &x[..] { + if y > 10 { + break; + } + y += *i; + } + assert_eq!(y, 11); +} diff --git a/src/test/ui/for-loop-while/foreach-external-iterators-hashmap-break-restart.rs b/src/test/ui/for-loop-while/foreach-external-iterators-hashmap-break-restart.rs new file mode 100644 index 00000000000..5d690807e05 --- /dev/null +++ b/src/test/ui/for-loop-while/foreach-external-iterators-hashmap-break-restart.rs @@ -0,0 +1,33 @@ +// run-pass + +use std::collections::HashMap; + +// This is a fancy one: it uses an external iterator established +// outside the loop, breaks, then _picks back up_ and continues +// iterating with it. + +pub fn main() { + let mut h = HashMap::new(); + let kvs = [(1, 10), (2, 20), (3, 30)]; + for &(k,v) in &kvs { + h.insert(k,v); + } + let mut x = 0; + let mut y = 0; + + let mut i = h.iter(); + + for (&k,&v) in i.by_ref() { + x += k; + y += v; + break; + } + + for (&k,&v) in i { + x += k; + y += v; + } + + assert_eq!(x, 6); + assert_eq!(y, 60); +} diff --git a/src/test/ui/for-loop-while/foreach-external-iterators-hashmap.rs b/src/test/ui/for-loop-while/foreach-external-iterators-hashmap.rs new file mode 100644 index 00000000000..9f2ca05cdb6 --- /dev/null +++ b/src/test/ui/for-loop-while/foreach-external-iterators-hashmap.rs @@ -0,0 +1,19 @@ +// run-pass + +use std::collections::HashMap; + +pub fn main() { + let mut h = HashMap::new(); + let kvs = [(1, 10), (2, 20), (3, 30)]; + for &(k,v) in &kvs { + h.insert(k,v); + } + let mut x = 0; + let mut y = 0; + for (&k,&v) in &h { + x += k; + y += v; + } + assert_eq!(x, 6); + assert_eq!(y, 60); +} diff --git a/src/test/ui/for-loop-while/foreach-external-iterators-loop.rs b/src/test/ui/for-loop-while/foreach-external-iterators-loop.rs new file mode 100644 index 00000000000..78af195bc20 --- /dev/null +++ b/src/test/ui/for-loop-while/foreach-external-iterators-loop.rs @@ -0,0 +1,13 @@ +// run-pass + +pub fn main() { + let x = [1; 100]; + let mut y = 0; + for (n,i) in x.iter().enumerate() { + if n < 10 { + continue; + } + y += *i; + } + assert_eq!(y, 90); +} diff --git a/src/test/ui/for-loop-while/foreach-external-iterators-nested.rs b/src/test/ui/for-loop-while/foreach-external-iterators-nested.rs new file mode 100644 index 00000000000..8a95f160a1a --- /dev/null +++ b/src/test/ui/for-loop-while/foreach-external-iterators-nested.rs @@ -0,0 +1,15 @@ +// run-pass + +pub fn main() { + let x = [1; 100]; + let y = [2; 100]; + let mut p = 0; + let mut q = 0; + for i in &x[..] { + for j in &y[..] { + p += *j; + } + q += *i + p; + } + assert_eq!(q, 1010100); +} diff --git a/src/test/ui/for-loop-while/foreach-external-iterators.rs b/src/test/ui/for-loop-while/foreach-external-iterators.rs new file mode 100644 index 00000000000..24ecfe9b60d --- /dev/null +++ b/src/test/ui/for-loop-while/foreach-external-iterators.rs @@ -0,0 +1,10 @@ +// run-pass + +pub fn main() { + let x = [1; 100]; + let mut y = 0; + for i in &x[..] { + y += *i + } + assert_eq!(y, 100); +} diff --git a/src/test/ui/for-loop-while/foreach-nested.rs b/src/test/ui/for-loop-while/foreach-nested.rs new file mode 100644 index 00000000000..bb6edbc0797 --- /dev/null +++ b/src/test/ui/for-loop-while/foreach-nested.rs @@ -0,0 +1,16 @@ +// run-pass + + +fn two<F>(mut it: F) where F: FnMut(isize) { it(0); it(1); } + +pub fn main() { + let mut a: Vec<isize> = vec![-1, -1, -1, -1]; + let mut p: isize = 0; + two(|i| { + two(|j| { a[p as usize] = 10 * i + j; p += 1; }) + }); + assert_eq!(a[0], 0); + assert_eq!(a[1], 1); + assert_eq!(a[2], 10); + assert_eq!(a[3], 11); +} diff --git a/src/test/ui/for-loop-while/foreach-put-structured.rs b/src/test/ui/for-loop-while/foreach-put-structured.rs new file mode 100644 index 00000000000..3a47fcf3415 --- /dev/null +++ b/src/test/ui/for-loop-while/foreach-put-structured.rs @@ -0,0 +1,22 @@ +// run-pass + + +fn pairs<F>(mut it: F) where F: FnMut((isize, isize)) { + let mut i: isize = 0; + let mut j: isize = 0; + while i < 10 { it((i, j)); i += 1; j += i; } +} + +pub fn main() { + let mut i: isize = 10; + let mut j: isize = 0; + pairs(|p| { + let (_0, _1) = p; + println!("{}", _0); + println!("{}", _1); + assert_eq!(_0 + 10, i); + i += 1; + j = _1; + }); + assert_eq!(j, 45); +} diff --git a/src/test/ui/for-loop-while/foreach-simple-outer-slot.rs b/src/test/ui/for-loop-while/foreach-simple-outer-slot.rs new file mode 100644 index 00000000000..a8d42a789ba --- /dev/null +++ b/src/test/ui/for-loop-while/foreach-simple-outer-slot.rs @@ -0,0 +1,16 @@ +// run-pass + + + +pub fn main() { + let mut sum: isize = 0; + first_ten(|i| { println!("main"); println!("{}", i); sum = sum + i; }); + println!("sum"); + println!("{}", sum); + assert_eq!(sum, 45); +} + +fn first_ten<F>(mut it: F) where F: FnMut(isize) { + let mut i: isize = 0; + while i < 10 { println!("first_ten"); it(i); i = i + 1; } +} diff --git a/src/test/ui/for-loop-while/label_break_value.rs b/src/test/ui/for-loop-while/label_break_value.rs new file mode 100644 index 00000000000..eb5be7742e0 --- /dev/null +++ b/src/test/ui/for-loop-while/label_break_value.rs @@ -0,0 +1,116 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_assignments)] +#![feature(label_break_value)] + +// Test control flow to follow label_break_value semantics +fn label_break(a: bool, b: bool) -> u32 { + let mut v = 0; + 'b: { + v = 1; + if a { + break 'b; + } + v = 2; + if b { + break 'b; + } + v = 3; + } + return v; +} + +// Test that values can be returned +fn break_value(a: bool, b: bool) -> u32 { + let result = 'block: { + if a { break 'block 1; } + if b { break 'block 2; } + 3 + }; + result +} + +// Test nesting of labeled blocks +// here we only check that it compiles +fn label_break_nested() { + 'b: { + println!("hi"); + if false { + break 'b; + } + 'c: { + if false { + break 'b; + } + break 'c; + } + println!("hello"); + if true { + break 'b; + } + } +} + +// Tests for mixing labeled blocks with loop constructs +// This function should be the identity function +fn label_break_mixed(v: u32) -> u32 { + let mut r = 0; + 'b: { + // Unlabeled break still works + // (only crossing boundaries is an error) + loop { + break; + } + if v == 0 { + break 'b; + } + // Labeled breaking an inner loop still works + 'c: loop { + if r == 1 { + break 'c; + } + r += 1; + } + assert_eq!(r, 1); + if v == 1 { + break 'b; + } + // Labeled breaking an outer loop still works + 'd: loop { + 'e: { + if v == r { + break 'b; + } + if r == 5 { + break 'd; + } + r += 1; + } + } + assert_eq!(r, 5); + assert!(v > r); + // Here we test return from inside a labeled block + return v; + } + r +} + +pub fn main() { + assert_eq!(label_break(true, false), 1); + assert_eq!(label_break(false, true), 2); + assert_eq!(label_break(false, false), 3); + + assert_eq!(break_value(true, false), 1); + assert_eq!(break_value(false, true), 2); + assert_eq!(break_value(false, false), 3); + + assert_eq!(label_break_mixed(0), 0); + assert_eq!(label_break_mixed(1), 1); + assert_eq!(label_break_mixed(2), 2); + assert_eq!(label_break_mixed(3), 3); + assert_eq!(label_break_mixed(4), 4); + 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 +} diff --git a/src/test/ui/for-loop-while/labeled-break.rs b/src/test/ui/for-loop-while/labeled-break.rs new file mode 100644 index 00000000000..4dacc57574f --- /dev/null +++ b/src/test/ui/for-loop-while/labeled-break.rs @@ -0,0 +1,22 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main() { + 'foo: loop { + loop { + break 'foo; + } + } + + 'bar: for _ in 0..100 { + loop { + break 'bar; + } + } + + 'foobar: while 1 + 1 == 2 { + loop { + break 'foobar; + } + } +} diff --git a/src/test/ui/for-loop-while/linear-for-loop.rs b/src/test/ui/for-loop-while/linear-for-loop.rs new file mode 100644 index 00000000000..3c573db1d77 --- /dev/null +++ b/src/test/ui/for-loop-while/linear-for-loop.rs @@ -0,0 +1,23 @@ +// run-pass +pub fn main() { + let x = vec![1, 2, 3]; + let mut y = 0; + for i in &x { println!("{}", *i); y += *i; } + println!("{}", y); + assert_eq!(y, 6); + let s = "hello there".to_string(); + let mut i: isize = 0; + for c in s.bytes() { + if i == 0 { assert_eq!(c, 'h' as u8); } + if i == 1 { assert_eq!(c, 'e' as u8); } + if i == 2 { assert_eq!(c, 'l' as u8); } + if i == 3 { assert_eq!(c, 'l' as u8); } + if i == 4 { assert_eq!(c, 'o' as u8); } + // ... + + i += 1; + println!("{}", i); + println!("{}", c); + } + assert_eq!(i, 11); +} diff --git a/src/test/ui/for-loop-while/liveness-assign-imm-local-after-loop.rs b/src/test/ui/for-loop-while/liveness-assign-imm-local-after-loop.rs new file mode 100644 index 00000000000..11b6971656f --- /dev/null +++ b/src/test/ui/for-loop-while/liveness-assign-imm-local-after-loop.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_assignments)] +// pretty-expanded FIXME #23616 + +#![allow(unreachable_code)] +#![allow(unused_variables)] + +fn test(_cond: bool) { + let v: isize; + v = 1; + loop { } // loop never terminates, so no error is reported + v = 2; +} + +pub fn main() { + // note: don't call test()... :) +} diff --git a/src/test/ui/for-loop-while/liveness-loop-break.rs b/src/test/ui/for-loop-while/liveness-loop-break.rs new file mode 100644 index 00000000000..60a63bccb10 --- /dev/null +++ b/src/test/ui/for-loop-while/liveness-loop-break.rs @@ -0,0 +1,13 @@ +// run-pass +fn test() { + let v; + loop { + v = 3; + break; + } + println!("{}", v); +} + +pub fn main() { + test(); +} diff --git a/src/test/ui/for-loop-while/liveness-move-in-loop.rs b/src/test/ui/for-loop-while/liveness-move-in-loop.rs new file mode 100644 index 00000000000..ce73d6335cb --- /dev/null +++ b/src/test/ui/for-loop-while/liveness-move-in-loop.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(dead_code)] + +// pretty-expanded FIXME #23616 + +fn take(x: isize) -> isize {x} + +fn the_loop() { + let mut list = Vec::new(); + loop { + let x = 5; + if x > 3 { + list.push(take(x)); + } else { + break; + } + } +} + +pub fn main() {} diff --git a/src/test/ui/for-loop-while/loop-break-cont-1.rs b/src/test/ui/for-loop-while/loop-break-cont-1.rs new file mode 100644 index 00000000000..f207746f085 --- /dev/null +++ b/src/test/ui/for-loop-while/loop-break-cont-1.rs @@ -0,0 +1,9 @@ +// run-pass + +pub fn main() { + let _i = 0_usize; + loop { + break; + } + assert!(true); +} diff --git a/src/test/ui/for-loop-while/loop-break-cont.rs b/src/test/ui/for-loop-while/loop-break-cont.rs new file mode 100644 index 00000000000..92d5a32c62b --- /dev/null +++ b/src/test/ui/for-loop-while/loop-break-cont.rs @@ -0,0 +1,39 @@ +// run-pass +pub fn main() { + let mut i = 0_usize; + loop { + println!("a"); + i += 1_usize; + if i == 10_usize { + break; + } + } + assert_eq!(i, 10_usize); + let mut is_even = false; + loop { + if i == 21_usize { + break; + } + println!("b"); + is_even = false; + i += 1_usize; + if i % 2_usize != 0_usize { + continue; + } + is_even = true; + } + assert!(!is_even); + loop { + println!("c"); + if i == 22_usize { + break; + } + is_even = false; + i += 1_usize; + if i % 2_usize != 0_usize { + continue; + } + is_even = true; + } + assert!(is_even); +} diff --git a/src/test/ui/for-loop-while/loop-break-value.rs b/src/test/ui/for-loop-while/loop-break-value.rs new file mode 100644 index 00000000000..e1edbbb929e --- /dev/null +++ b/src/test/ui/for-loop-while/loop-break-value.rs @@ -0,0 +1,138 @@ +// run-pass +#![allow(unreachable_code)] +#![feature(never_type)] + +#[allow(unused)] +fn never_returns() { + loop { + break loop {}; + } +} + +pub fn main() { + let value = 'outer: loop { + if 1 == 1 { + break 13; + } else { + let _never: ! = loop { + break loop { + break 'outer panic!(); + } + }; + } + }; + assert_eq!(value, 13); + + let x = [1, 3u32, 5]; + let y = [17]; + let z = []; + let coerced: &[_] = loop { + match 2 { + 1 => break &x, + 2 => break &y, + 3 => break &z, + _ => (), + } + }; + assert_eq!(coerced, &[17u32]); + + let trait_unified = loop { + break if true { + break Default::default() + } else { + break [13, 14] + }; + }; + assert_eq!(trait_unified, [0, 0]); + + let trait_unified_2 = loop { + if false { + break [String::from("Hello")] + } else { + break Default::default() + }; + }; + assert_eq!(trait_unified_2, [""]); + + let trait_unified_3 = loop { + break if false { + break [String::from("Hello")] + } else { + ["Yes".into()] + }; + }; + assert_eq!(trait_unified_3, ["Yes"]); + + let regular_break = loop { + if true { + break; + } else { + break break Default::default(); + } + }; + assert_eq!(regular_break, ()); + + let regular_break_2 = loop { + if true { + break Default::default(); + } else { + break; + } + }; + assert_eq!(regular_break_2, ()); + + let regular_break_3 = loop { + break if true { + Default::default() + } else { + break; + } + }; + assert_eq!(regular_break_3, ()); + + let regular_break_4 = loop { + break (); + break; + }; + assert_eq!(regular_break_4, ()); + + let regular_break_5 = loop { + break; + break (); + }; + assert_eq!(regular_break_5, ()); + + let nested_break_value = 'outer2: loop { + let _a: u32 = 'inner: loop { + if true { + break 'outer2 "hello"; + } else { + break 'inner 17; + } + }; + panic!(); + }; + assert_eq!(nested_break_value, "hello"); + + let break_from_while_cond = loop { + 'inner_loop: while break 'inner_loop { + panic!(); + } + break 123; + }; + assert_eq!(break_from_while_cond, 123); + + let break_from_while_to_outer = 'outer_loop: loop { + while break 'outer_loop 567 { + panic!("from_inner"); + } + panic!("from outer"); + }; + assert_eq!(break_from_while_to_outer, 567); + + let rust = true; + let value = loop { + break rust; + }; + assert!(value); +} diff --git a/src/test/ui/for-loop-while/loop-diverges.rs b/src/test/ui/for-loop-while/loop-diverges.rs new file mode 100644 index 00000000000..f657bf9e0b3 --- /dev/null +++ b/src/test/ui/for-loop-while/loop-diverges.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(unused_parens)] +// pretty-expanded FIXME #23616 + +/* Make sure a loop{} can be the tailexpr in the body +of a diverging function */ + +fn forever() -> ! { + loop{} +} + +pub fn main() { + if (1 == 2) { forever(); } +} diff --git a/src/test/ui/for-loop-while/loop-label-shadowing.rs b/src/test/ui/for-loop-while/loop-label-shadowing.rs new file mode 100644 index 00000000000..acb53e254bb --- /dev/null +++ b/src/test/ui/for-loop-while/loop-label-shadowing.rs @@ -0,0 +1,11 @@ +// run-pass +// Issue #12512. + +// pretty-expanded FIXME #23616 + +fn main() { + let mut foo = Vec::new(); + 'foo: for i in &[1, 2, 3] { + foo.push(*i); + } +} diff --git a/src/test/ui/for-loop-while/loop-labeled-break-value.rs b/src/test/ui/for-loop-while/loop-labeled-break-value.rs new file mode 100644 index 00000000000..cc8f826983b --- /dev/null +++ b/src/test/ui/for-loop-while/loop-labeled-break-value.rs @@ -0,0 +1,11 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn main() { + 'outer: loop { + let _: i32 = loop { break 'outer }; + } + 'outer2: loop { + let _: i32 = loop { loop { break 'outer2 } }; + } +} diff --git a/src/test/ui/for-loop-while/loop-no-reinit-needed-post-bot.rs b/src/test/ui/for-loop-while/loop-no-reinit-needed-post-bot.rs new file mode 100644 index 00000000000..1b5db20129d --- /dev/null +++ b/src/test/ui/for-loop-while/loop-no-reinit-needed-post-bot.rs @@ -0,0 +1,34 @@ +// run-pass +// pretty-expanded FIXME #23616 + +struct S; +// Ensure S is moved, not copied, on assignment. +impl Drop for S { fn drop(&mut self) { } } + +// user-defined function "returning" bottom (i.e., no return at all). +fn my_panic() -> ! { loop {} } + +pub fn step(f: bool) { + let mut g = S; + let mut i = 0; + loop + { + if i > 10 { break; } else { i += 1; } + + let _g = g; + + if f { + // re-initialize g, but only before restarting loop. + g = S; + continue; + } + + my_panic(); + + // we never get here, so we do not need to re-initialize g. + } +} + +pub fn main() { + step(true); +} diff --git a/src/test/ui/for-loop-while/loop-scope.rs b/src/test/ui/for-loop-while/loop-scope.rs new file mode 100644 index 00000000000..73324a3e1bd --- /dev/null +++ b/src/test/ui/for-loop-while/loop-scope.rs @@ -0,0 +1,8 @@ +// run-pass + +pub fn main() { + let x = vec![10, 20, 30]; + let mut sum = 0; + for x in &x { sum += *x; } + assert_eq!(sum, 60); +} diff --git a/src/test/ui/for-loop-while/while-cont.rs b/src/test/ui/for-loop-while/while-cont.rs new file mode 100644 index 00000000000..a864e8ef70a --- /dev/null +++ b/src/test/ui/for-loop-while/while-cont.rs @@ -0,0 +1,11 @@ +// run-pass +// Issue #825: Should recheck the loop condition after continuing +pub fn main() { + let mut i = 1; + while i > 0 { + assert!((i > 0)); + println!("{}", i); + i -= 1; + continue; + } +} diff --git a/src/test/ui/for-loop-while/while-flow-graph.rs b/src/test/ui/for-loop-while/while-flow-graph.rs new file mode 100644 index 00000000000..1748964a7b2 --- /dev/null +++ b/src/test/ui/for-loop-while/while-flow-graph.rs @@ -0,0 +1,6 @@ +// run-pass + + +// pretty-expanded FIXME #23616 + +pub fn main() { let x: isize = 10; while x == 10 && x == 11 { let _y = 0xf00_usize; } } diff --git a/src/test/ui/for-loop-while/while-label.rs b/src/test/ui/for-loop-while/while-label.rs new file mode 100644 index 00000000000..5abc41daf94 --- /dev/null +++ b/src/test/ui/for-loop-while/while-label.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(unreachable_code)] + + +pub fn main() { + let mut i = 100; + 'w: while 1 + 1 == 2 { + i -= 1; + if i == 95 { + break 'w; + panic!("Should have broken out of loop"); + } + } + assert_eq!(i, 95); +} diff --git a/src/test/ui/for-loop-while/while-let.rs b/src/test/ui/for-loop-while/while-let.rs new file mode 100644 index 00000000000..b9d70ff0b9d --- /dev/null +++ b/src/test/ui/for-loop-while/while-let.rs @@ -0,0 +1,46 @@ +// run-pass + +use std::collections::BinaryHeap; + +fn make_pq() -> BinaryHeap<isize> { + BinaryHeap::from(vec![1,2,3]) +} + +pub fn main() { + let mut pq = make_pq(); + let mut sum = 0; + while let Some(x) = pq.pop() { + sum += x; + } + assert_eq!(sum, 6); + + pq = make_pq(); + sum = 0; + 'a: while let Some(x) = pq.pop() { + sum += x; + if x == 2 { + break 'a; + } + } + assert_eq!(sum, 5); + + pq = make_pq(); + sum = 0; + 'a2: while let Some(x) = pq.pop() { + if x == 3 { + continue 'a2; + } + sum += x; + } + assert_eq!(sum, 3); + + let mut pq1 = make_pq(); + sum = 0; + while let Some(x) = pq1.pop() { + let mut pq2 = make_pq(); + while let Some(y) = pq2.pop() { + sum += x * y; + } + } + assert_eq!(sum, 6 + 12 + 18); +} diff --git a/src/test/ui/for-loop-while/while-loop-constraints-2.rs b/src/test/ui/for-loop-while/while-loop-constraints-2.rs new file mode 100644 index 00000000000..3c5cdf06cd8 --- /dev/null +++ b/src/test/ui/for-loop-while/while-loop-constraints-2.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(unused_assignments)] +#![allow(unused_variables)] + +pub fn main() { + let mut y: isize = 42; + let mut z: isize = 42; + let mut x: isize; + while z < 50 { + z += 1; + while false { x = y; y = z; } + println!("{}", y); + } + assert!((y == 42 && z == 50)); +} diff --git a/src/test/ui/for-loop-while/while-prelude-drop.rs b/src/test/ui/for-loop-while/while-prelude-drop.rs new file mode 100644 index 00000000000..196b9daf6ec --- /dev/null +++ b/src/test/ui/for-loop-while/while-prelude-drop.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(non_camel_case_types)] + +use std::string::String; + +#[derive(PartialEq)] +enum t { a, b(String), } + +fn make(i: isize) -> t { + if i > 10 { return t::a; } + let mut s = String::from("hello"); + // Ensure s is non-const. + + s.push_str("there"); + return t::b(s); +} + +pub fn main() { + let mut i = 0; + + + // The auto slot for the result of make(i) should not leak. + while make(i) != t::a { i += 1; } +} diff --git a/src/test/ui/for-loop-while/while-with-break.rs b/src/test/ui/for-loop-while/while-with-break.rs new file mode 100644 index 00000000000..a9d52dda544 --- /dev/null +++ b/src/test/ui/for-loop-while/while-with-break.rs @@ -0,0 +1,17 @@ +// run-pass + +pub fn main() { + let mut i: isize = 90; + while i < 100 { + println!("{}", i); + i = i + 1; + if i == 95 { + let _v: Vec<isize> = + vec![1, 2, 3, 4, 5]; // we check that it is freed by break + + println!("breaking"); + break; + } + } + assert_eq!(i, 95); +} diff --git a/src/test/ui/for-loop-while/while.rs b/src/test/ui/for-loop-while/while.rs new file mode 100644 index 00000000000..90f718a3483 --- /dev/null +++ b/src/test/ui/for-loop-while/while.rs @@ -0,0 +1,13 @@ +// run-pass + + +pub fn main() { + let mut x: isize = 10; + let mut y: isize = 0; + while y < x { println!("{}", y); println!("hello"); y = y + 1; } + while x > 0 { + println!("goodbye"); + x = x - 1; + println!("{}", x); + } +} |
