about summary refs log tree commit diff
path: root/src/test/ui/for-loop-while
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-07-27 01:33:01 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-07-27 18:56:16 +0300
commit9be35f82c1abf2ecbab489bca9eca138ea648312 (patch)
tree69888506e34af447d9748c0d542de3ba1dd76210 /src/test/ui/for-loop-while
parentca9faa52f5ada0054b1fa27d97aedf448afb059b (diff)
downloadrust-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')
-rw-r--r--src/test/ui/for-loop-while/auto-loop.rs10
-rw-r--r--src/test/ui/for-loop-while/break-value.rs7
-rw-r--r--src/test/ui/for-loop-while/break.rs25
-rw-r--r--src/test/ui/for-loop-while/for-destruct.rs9
-rw-r--r--src/test/ui/for-loop-while/for-loop-goofiness.rs16
-rw-r--r--src/test/ui/for-loop-while/for-loop-has-unit-body.rs13
-rw-r--r--src/test/ui/for-loop-while/for-loop-into-iterator.rs19
-rw-r--r--src/test/ui/for-loop-while/for-loop-lifetime-of-unbound-values.rs34
-rw-r--r--src/test/ui/for-loop-while/for-loop-macro.rs11
-rw-r--r--src/test/ui/for-loop-while/for-loop-mut-ref-element.rs6
-rw-r--r--src/test/ui/for-loop-while/for-loop-no-std.rs14
-rw-r--r--src/test/ui/for-loop-while/for-loop-panic.rs4
-rw-r--r--src/test/ui/for-loop-while/for-loop-unconstrained-element-type-i32-fallback.rs11
-rw-r--r--src/test/ui/for-loop-while/foreach-external-iterators-break.rs13
-rw-r--r--src/test/ui/for-loop-while/foreach-external-iterators-hashmap-break-restart.rs33
-rw-r--r--src/test/ui/for-loop-while/foreach-external-iterators-hashmap.rs19
-rw-r--r--src/test/ui/for-loop-while/foreach-external-iterators-loop.rs13
-rw-r--r--src/test/ui/for-loop-while/foreach-external-iterators-nested.rs15
-rw-r--r--src/test/ui/for-loop-while/foreach-external-iterators.rs10
-rw-r--r--src/test/ui/for-loop-while/foreach-nested.rs16
-rw-r--r--src/test/ui/for-loop-while/foreach-put-structured.rs22
-rw-r--r--src/test/ui/for-loop-while/foreach-simple-outer-slot.rs16
-rw-r--r--src/test/ui/for-loop-while/label_break_value.rs116
-rw-r--r--src/test/ui/for-loop-while/labeled-break.rs22
-rw-r--r--src/test/ui/for-loop-while/linear-for-loop.rs23
-rw-r--r--src/test/ui/for-loop-while/liveness-assign-imm-local-after-loop.rs18
-rw-r--r--src/test/ui/for-loop-while/liveness-loop-break.rs13
-rw-r--r--src/test/ui/for-loop-while/liveness-move-in-loop.rs20
-rw-r--r--src/test/ui/for-loop-while/loop-break-cont-1.rs9
-rw-r--r--src/test/ui/for-loop-while/loop-break-cont.rs39
-rw-r--r--src/test/ui/for-loop-while/loop-break-value.rs138
-rw-r--r--src/test/ui/for-loop-while/loop-diverges.rs14
-rw-r--r--src/test/ui/for-loop-while/loop-label-shadowing.rs11
-rw-r--r--src/test/ui/for-loop-while/loop-labeled-break-value.rs11
-rw-r--r--src/test/ui/for-loop-while/loop-no-reinit-needed-post-bot.rs34
-rw-r--r--src/test/ui/for-loop-while/loop-scope.rs8
-rw-r--r--src/test/ui/for-loop-while/while-cont.rs11
-rw-r--r--src/test/ui/for-loop-while/while-flow-graph.rs6
-rw-r--r--src/test/ui/for-loop-while/while-label.rs15
-rw-r--r--src/test/ui/for-loop-while/while-let.rs46
-rw-r--r--src/test/ui/for-loop-while/while-loop-constraints-2.rs15
-rw-r--r--src/test/ui/for-loop-while/while-prelude-drop.rs24
-rw-r--r--src/test/ui/for-loop-while/while-with-break.rs17
-rw-r--r--src/test/ui/for-loop-while/while.rs13
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);
+    }
+}