about summary refs log tree commit diff
path: root/src/test/ui/borrowck
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/borrowck
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/borrowck')
-rw-r--r--src/test/ui/borrowck/borrowck-assign-to-subfield.rs23
-rw-r--r--src/test/ui/borrowck/borrowck-assignment-to-static-mut.rs11
-rw-r--r--src/test/ui/borrowck/borrowck-binding-mutbl.rs16
-rw-r--r--src/test/ui/borrowck/borrowck-borrow-from-expr-block.rs18
-rw-r--r--src/test/ui/borrowck/borrowck-borrow-of-mut-base-ptr-safe.rs21
-rw-r--r--src/test/ui/borrowck/borrowck-closures-two-imm.rs41
-rw-r--r--src/test/ui/borrowck/borrowck-fixed-length-vecs.rs7
-rw-r--r--src/test/ui/borrowck/borrowck-freeze-frozen-mut.rs28
-rw-r--r--src/test/ui/borrowck/borrowck-lend-args.rs21
-rw-r--r--src/test/ui/borrowck/borrowck-macro-interaction-issue-6304.rs38
-rw-r--r--src/test/ui/borrowck/borrowck-move-by-capture-ok.rs8
-rw-r--r--src/test/ui/borrowck/borrowck-multiple-borrows-interior-boxes.rs20
-rw-r--r--src/test/ui/borrowck/borrowck-mut-uniq.rs33
-rw-r--r--src/test/ui/borrowck/borrowck-mut-vec-as-imm-slice.rs16
-rw-r--r--src/test/ui/borrowck/borrowck-pat-enum.rs39
-rw-r--r--src/test/ui/borrowck/borrowck-pat-reassign-no-binding.rs14
-rw-r--r--src/test/ui/borrowck/borrowck-rvalues-mutable.rs34
-rw-r--r--src/test/ui/borrowck/borrowck-scope-of-deref-issue-4666.rs42
-rw-r--r--src/test/ui/borrowck/borrowck-static-item-in-fn.rs9
-rw-r--r--src/test/ui/borrowck/borrowck-trait-lifetime.rs18
-rw-r--r--src/test/ui/borrowck/borrowck-uniq-via-ref.rs49
-rw-r--r--src/test/ui/borrowck/borrowck-univariant-enum.rs25
-rw-r--r--src/test/ui/borrowck/borrowck-unsafe-static-mutable-borrows.rs20
-rw-r--r--src/test/ui/borrowck/borrowck-unused-mut-locals.rs46
-rw-r--r--src/test/ui/borrowck/issue-62007-assign-box.rs27
-rw-r--r--src/test/ui/borrowck/issue-62007-assign-field.rs26
-rw-r--r--src/test/ui/borrowck/two-phase-baseline.rs9
-rw-r--r--src/test/ui/borrowck/two-phase-bin-ops.rs35
-rw-r--r--src/test/ui/borrowck/two-phase-control-flow-split-before-activation.rs15
29 files changed, 709 insertions, 0 deletions
diff --git a/src/test/ui/borrowck/borrowck-assign-to-subfield.rs b/src/test/ui/borrowck/borrowck-assign-to-subfield.rs
new file mode 100644
index 00000000000..050d702b625
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-assign-to-subfield.rs
@@ -0,0 +1,23 @@
+// run-pass
+// pretty-expanded FIXME #23616
+
+pub fn main() {
+    struct A {
+        a: isize,
+        w: B,
+    }
+    struct B {
+        a: isize
+    }
+    let mut p = A {
+        a: 1,
+        w: B {a: 1},
+    };
+
+    // even though `x` is not declared as a mutable field,
+    // `p` as a whole is mutable, so it can be modified.
+    p.a = 2;
+
+    // this is true for an interior field too
+    p.w.a = 2;
+}
diff --git a/src/test/ui/borrowck/borrowck-assignment-to-static-mut.rs b/src/test/ui/borrowck/borrowck-assignment-to-static-mut.rs
new file mode 100644
index 00000000000..72bf43da95e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-assignment-to-static-mut.rs
@@ -0,0 +1,11 @@
+// run-pass
+#![allow(dead_code)]
+// Test taken from #45641 (https://github.com/rust-lang/rust/issues/45641)
+
+static mut Y: u32 = 0;
+
+unsafe fn should_ok() {
+    Y = 1;
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-binding-mutbl.rs b/src/test/ui/borrowck/borrowck-binding-mutbl.rs
new file mode 100644
index 00000000000..c2d2e02ec15
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-binding-mutbl.rs
@@ -0,0 +1,16 @@
+// run-pass
+
+struct F { f: Vec<isize> }
+
+fn impure(_v: &[isize]) {
+}
+
+pub fn main() {
+    let mut x = F {f: vec![3]};
+
+    match x {
+      F {f: ref mut v} => {
+        impure(v);
+      }
+    }
+}
diff --git a/src/test/ui/borrowck/borrowck-borrow-from-expr-block.rs b/src/test/ui/borrowck/borrowck-borrow-from-expr-block.rs
new file mode 100644
index 00000000000..15c6e8bf210
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-from-expr-block.rs
@@ -0,0 +1,18 @@
+// run-pass
+#![feature(box_syntax)]
+
+fn borrow<F>(x: &isize, f: F) where F: FnOnce(&isize) {
+    f(x)
+}
+
+fn test1(x: &Box<isize>) {
+    borrow(&*(*x).clone(), |p| {
+        let x_a = &**x as *const isize;
+        assert!((x_a as usize) != (p as *const isize as usize));
+        assert_eq!(unsafe{*x_a}, *p);
+    })
+}
+
+pub fn main() {
+    test1(&box 22);
+}
diff --git a/src/test/ui/borrowck/borrowck-borrow-of-mut-base-ptr-safe.rs b/src/test/ui/borrowck/borrowck-borrow-of-mut-base-ptr-safe.rs
new file mode 100644
index 00000000000..2839a9195a0
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-borrow-of-mut-base-ptr-safe.rs
@@ -0,0 +1,21 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_mut)]
+#![allow(unused_variables)]
+// Test that freezing an `&mut` pointer while referent is
+// frozen is legal.
+//
+// Example from src/librustc_borrowck/borrowck/README.md
+
+// pretty-expanded FIXME #23616
+
+fn foo<'a>(mut t0: &'a mut isize,
+           mut t1: &'a mut isize) {
+    let p: &isize = &*t0; // Freezes `*t0`
+    let mut t2 = &t0;
+    let q: &isize = &**t2; // Freezes `*t0`, but that's ok...
+    let r: &isize = &*t0; // ...after all, could do same thing directly.
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-closures-two-imm.rs b/src/test/ui/borrowck/borrowck-closures-two-imm.rs
new file mode 100644
index 00000000000..ab135194a09
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-two-imm.rs
@@ -0,0 +1,41 @@
+// run-pass
+// Tests that two closures can simultaneously have immutable
+// access to the variable, whether that immutable access be used
+// for direct reads or for taking immutable ref. Also check
+// that the main function can read the variable too while
+// the closures are in scope. Issue #6801.
+
+
+fn a() -> i32 {
+    let mut x = 3;
+    x += 1;
+    let c1 = || x * 4;
+    let c2 = || x * 5;
+    c1() * c2() * x
+}
+
+fn get(x: &i32) -> i32 {
+    *x * 4
+}
+
+fn b() -> i32 {
+    let mut x = 3;
+    x += 1;
+    let c1 = || get(&x);
+    let c2 = || get(&x);
+    c1() * c2() * x
+}
+
+fn c() -> i32 {
+    let mut x = 3;
+    x += 1;
+    let c1 = || x * 5;
+    let c2 = || get(&x);
+    c1() * c2() * x
+}
+
+pub fn main() {
+    assert_eq!(a(), 1280);
+    assert_eq!(b(), 1024);
+    assert_eq!(c(), 1280);
+}
diff --git a/src/test/ui/borrowck/borrowck-fixed-length-vecs.rs b/src/test/ui/borrowck/borrowck-fixed-length-vecs.rs
new file mode 100644
index 00000000000..126323d8d24
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-fixed-length-vecs.rs
@@ -0,0 +1,7 @@
+// run-pass
+
+pub fn main() {
+    let x = [22];
+    let y = &x[0];
+    assert_eq!(*y, 22);
+}
diff --git a/src/test/ui/borrowck/borrowck-freeze-frozen-mut.rs b/src/test/ui/borrowck/borrowck-freeze-frozen-mut.rs
new file mode 100644
index 00000000000..199931d6d1e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-freeze-frozen-mut.rs
@@ -0,0 +1,28 @@
+// run-pass
+// Test that a `&mut` inside of an `&` is freezable.
+
+
+struct MutSlice<'a, T:'a> {
+    data: &'a mut [T]
+}
+
+fn get<'a, T>(ms: &'a MutSlice<'a, T>, index: usize) -> &'a T {
+    &ms.data[index]
+}
+
+pub fn main() {
+    let mut data = [1, 2, 3];
+    {
+        let slice = MutSlice { data: &mut data };
+        slice.data[0] += 4;
+        let index0 = get(&slice, 0);
+        let index1 = get(&slice, 1);
+        let index2 = get(&slice, 2);
+        assert_eq!(*index0, 5);
+        assert_eq!(*index1, 2);
+        assert_eq!(*index2, 3);
+    }
+    assert_eq!(data[0], 5);
+    assert_eq!(data[1], 2);
+    assert_eq!(data[2], 3);
+}
diff --git a/src/test/ui/borrowck/borrowck-lend-args.rs b/src/test/ui/borrowck/borrowck-lend-args.rs
new file mode 100644
index 00000000000..d0ef2dcdd28
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-lend-args.rs
@@ -0,0 +1,21 @@
+// run-pass
+#![allow(dead_code)]
+
+// pretty-expanded FIXME #23616
+
+fn borrow(_v: &isize) {}
+
+fn borrow_from_arg_imm_ref(v: Box<isize>) {
+    borrow(&*v);
+}
+
+fn borrow_from_arg_mut_ref(v: &mut Box<isize>) {
+    borrow(&**v);
+}
+
+fn borrow_from_arg_copy(v: Box<isize>) {
+    borrow(&*v);
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-macro-interaction-issue-6304.rs b/src/test/ui/borrowck/borrowck-macro-interaction-issue-6304.rs
new file mode 100644
index 00000000000..628e49f574c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-macro-interaction-issue-6304.rs
@@ -0,0 +1,38 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(unconditional_recursion)]
+
+// Check that we do not ICE when compiling this
+// macro, which reuses the expression `$id`
+
+
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+
+struct Foo {
+  a: isize
+}
+
+pub enum Bar {
+  Bar1, Bar2(isize, Box<Bar>),
+}
+
+impl Foo {
+  fn elaborate_stm(&mut self, s: Box<Bar>) -> Box<Bar> {
+    macro_rules! declare {
+      ($id:expr, $rest:expr) => ({
+        self.check_id($id);
+        box Bar::Bar2($id, $rest)
+      })
+    }
+    match s {
+      box Bar::Bar2(id, rest) => declare!(id, self.elaborate_stm(rest)),
+      _ => panic!()
+    }
+  }
+
+  fn check_id(&mut self, s: isize) { panic!() }
+}
+
+pub fn main() { }
diff --git a/src/test/ui/borrowck/borrowck-move-by-capture-ok.rs b/src/test/ui/borrowck/borrowck-move-by-capture-ok.rs
new file mode 100644
index 00000000000..98e4b881893
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-by-capture-ok.rs
@@ -0,0 +1,8 @@
+// run-pass
+#![feature(box_syntax)]
+
+pub fn main() {
+    let bar: Box<_> = box 3;
+    let h = || -> isize { *bar };
+    assert_eq!(h(), 3);
+}
diff --git a/src/test/ui/borrowck/borrowck-multiple-borrows-interior-boxes.rs b/src/test/ui/borrowck/borrowck-multiple-borrows-interior-boxes.rs
new file mode 100644
index 00000000000..96d2663500e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-multiple-borrows-interior-boxes.rs
@@ -0,0 +1,20 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+// Test case from #39963.
+
+#[derive(Clone)]
+struct Foo(Option<Box<Foo>>, Option<Box<Foo>>);
+
+fn test(f: &mut Foo) {
+  match *f {
+    Foo(Some(ref mut left), Some(ref mut right)) => match **left {
+      Foo(Some(ref mut left), Some(ref mut right)) => panic!(),
+      _ => panic!(),
+    },
+    _ => panic!(),
+  }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-mut-uniq.rs b/src/test/ui/borrowck/borrowck-mut-uniq.rs
new file mode 100644
index 00000000000..80b3484e0fb
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-mut-uniq.rs
@@ -0,0 +1,33 @@
+// run-pass
+#![feature(box_syntax)]
+
+use std::mem::swap;
+
+#[derive(Debug)]
+struct Ints {sum: Box<isize>, values: Vec<isize> }
+
+fn add_int(x: &mut Ints, v: isize) {
+    *x.sum += v;
+    let mut values = Vec::new();
+    swap(&mut values, &mut x.values);
+    values.push(v);
+    swap(&mut values, &mut x.values);
+}
+
+fn iter_ints<F>(x: &Ints, mut f: F) -> bool where F: FnMut(&isize) -> bool {
+    let l = x.values.len();
+    (0..l).all(|i| f(&x.values[i]))
+}
+
+pub fn main() {
+    let mut ints: Box<_> = box Ints {sum: box 0, values: Vec::new()};
+    add_int(&mut *ints, 22);
+    add_int(&mut *ints, 44);
+
+    iter_ints(&*ints, |i| {
+        println!("isize = {:?}", *i);
+        true
+    });
+
+    println!("ints={:?}", ints);
+}
diff --git a/src/test/ui/borrowck/borrowck-mut-vec-as-imm-slice.rs b/src/test/ui/borrowck/borrowck-mut-vec-as-imm-slice.rs
new file mode 100644
index 00000000000..d2b0c01545e
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-mut-vec-as-imm-slice.rs
@@ -0,0 +1,16 @@
+// run-pass
+
+
+fn want_slice(v: &[isize]) -> isize {
+    let mut sum = 0;
+    for i in v { sum += *i; }
+    sum
+}
+
+fn has_mut_vec(v: Vec<isize> ) -> isize {
+    want_slice(&v)
+}
+
+pub fn main() {
+    assert_eq!(has_mut_vec(vec![1, 2, 3]), 6);
+}
diff --git a/src/test/ui/borrowck/borrowck-pat-enum.rs b/src/test/ui/borrowck/borrowck-pat-enum.rs
new file mode 100644
index 00000000000..7f9c5544d0b
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-pat-enum.rs
@@ -0,0 +1,39 @@
+// run-pass
+#![allow(dead_code)]
+// ignore-pretty issue #37199
+
+fn match_ref(v: Option<isize>) -> isize {
+    match v {
+      Some(ref i) => {
+        *i
+      }
+      None => {0}
+    }
+}
+
+fn match_ref_unused(v: Option<isize>) {
+    match v {
+      Some(_) => {}
+      None => {}
+    }
+}
+
+fn impure(_i: isize) {
+}
+
+fn match_imm_reg(v: &Option<isize>) {
+    match *v {
+      Some(ref i) => {impure(*i)} // OK because immutable
+      None => {}
+    }
+}
+
+fn match_mut_reg(v: &mut Option<isize>) {
+    match *v {
+      Some(ref i) => {impure(*i)} // OK, frozen
+      None => {}
+    }
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-pat-reassign-no-binding.rs b/src/test/ui/borrowck/borrowck-pat-reassign-no-binding.rs
new file mode 100644
index 00000000000..1362fd8ce4c
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-pat-reassign-no-binding.rs
@@ -0,0 +1,14 @@
+// run-pass
+
+pub fn main() {
+    let mut x = None;
+    match x {
+      None => {
+        // It is ok to reassign x here, because there is in
+        // fact no outstanding loan of x!
+        x = Some(0);
+      }
+      Some(_) => { }
+    }
+    assert_eq!(x, Some(0));
+}
diff --git a/src/test/ui/borrowck/borrowck-rvalues-mutable.rs b/src/test/ui/borrowck/borrowck-rvalues-mutable.rs
new file mode 100644
index 00000000000..c4695c942e1
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-rvalues-mutable.rs
@@ -0,0 +1,34 @@
+// run-pass
+
+struct Counter {
+    value: usize
+}
+
+impl Counter {
+    fn new(v: usize) -> Counter {
+        Counter {value: v}
+    }
+
+    fn inc<'a>(&'a mut self) -> &'a mut Counter {
+        self.value += 1;
+        self
+    }
+
+    fn get(&self) -> usize {
+        self.value
+    }
+
+    fn get_and_inc(&mut self) -> usize {
+        let v = self.value;
+        self.value += 1;
+        v
+    }
+}
+
+pub fn main() {
+    let v = Counter::new(22).get_and_inc();
+    assert_eq!(v, 22);
+
+    let v = Counter::new(22).inc().inc().get();
+    assert_eq!(v, 24);
+}
diff --git a/src/test/ui/borrowck/borrowck-scope-of-deref-issue-4666.rs b/src/test/ui/borrowck/borrowck-scope-of-deref-issue-4666.rs
new file mode 100644
index 00000000000..e89332ae31a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-scope-of-deref-issue-4666.rs
@@ -0,0 +1,42 @@
+// run-pass
+// Tests that the scope of the pointer returned from `get()` is
+// limited to the deref operation itself, and does not infect the
+// block as a whole.
+
+
+struct Box {
+    x: usize
+}
+
+impl Box {
+    fn get(&self) -> &usize {
+        &self.x
+    }
+    fn set(&mut self, x: usize) {
+        self.x = x;
+    }
+}
+
+fn fun1() {
+    // in the past, borrow checker behaved differently when
+    // init and decl of `v` were distinct
+    let v;
+    let mut a_box = Box {x: 0};
+    a_box.set(22);
+    v = *a_box.get();
+    a_box.set(v+1);
+    assert_eq!(23, *a_box.get());
+}
+
+fn fun2() {
+    let mut a_box = Box {x: 0};
+    a_box.set(22);
+    let v = *a_box.get();
+    a_box.set(v+1);
+    assert_eq!(23, *a_box.get());
+}
+
+pub fn main() {
+    fun1();
+    fun2();
+}
diff --git a/src/test/ui/borrowck/borrowck-static-item-in-fn.rs b/src/test/ui/borrowck/borrowck-static-item-in-fn.rs
new file mode 100644
index 00000000000..5f4379325a5
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-static-item-in-fn.rs
@@ -0,0 +1,9 @@
+// run-pass
+#![allow(dead_code)]
+// Regression test for issue #7740
+
+// pretty-expanded FIXME #23616
+
+pub fn main() {
+    static A: &'static char = &'A';
+}
diff --git a/src/test/ui/borrowck/borrowck-trait-lifetime.rs b/src/test/ui/borrowck/borrowck-trait-lifetime.rs
new file mode 100644
index 00000000000..8a6dfe76d60
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-trait-lifetime.rs
@@ -0,0 +1,18 @@
+// run-pass
+#![allow(unused_imports)]
+// This test verifies that casting from the same lifetime on a value
+// to the same lifetime on a trait succeeds. See issue #10766.
+
+// pretty-expanded FIXME #23616
+
+#![allow(dead_code)]
+
+use std::marker;
+
+fn main() {
+    trait T { fn foo(&self) {} }
+
+    fn f<'a, V: T>(v: &'a V) -> &'a dyn T {
+        v as &'a dyn T
+    }
+}
diff --git a/src/test/ui/borrowck/borrowck-uniq-via-ref.rs b/src/test/ui/borrowck/borrowck-uniq-via-ref.rs
new file mode 100644
index 00000000000..bdf7cc57a53
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-uniq-via-ref.rs
@@ -0,0 +1,49 @@
+// run-pass
+#![allow(dead_code)]
+
+// pretty-expanded FIXME #23616
+
+struct Rec {
+    f: Box<isize>,
+}
+
+struct Outer {
+    f: Inner
+}
+
+struct Inner {
+    g: Innermost
+}
+
+struct Innermost {
+    h: Box<isize>,
+}
+
+fn borrow(_v: &isize) {}
+
+fn box_mut(v: &mut Box<isize>) {
+    borrow(&**v); // OK: &mut -> &imm
+}
+
+fn box_mut_rec(v: &mut Rec) {
+    borrow(&*v.f); // OK: &mut -> &imm
+}
+
+fn box_mut_recs(v: &mut Outer) {
+    borrow(&*v.f.g.h); // OK: &mut -> &imm
+}
+
+fn box_imm(v: &Box<isize>) {
+    borrow(&**v); // OK
+}
+
+fn box_imm_rec(v: &Rec) {
+    borrow(&*v.f); // OK
+}
+
+fn box_imm_recs(v: &Outer) {
+    borrow(&*v.f.g.h); // OK
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/borrowck/borrowck-univariant-enum.rs b/src/test/ui/borrowck/borrowck-univariant-enum.rs
new file mode 100644
index 00000000000..c78e9475233
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-univariant-enum.rs
@@ -0,0 +1,25 @@
+// run-pass
+#![allow(non_camel_case_types)]
+
+use std::cell::Cell;
+
+#[derive(Copy, Clone)]
+enum newtype {
+    newvar(isize)
+}
+
+pub fn main() {
+
+    // Test that borrowck treats enums with a single variant
+    // specially.
+
+    let x = &Cell::new(5);
+    let y = &Cell::new(newtype::newvar(3));
+    let z = match y.get() {
+      newtype::newvar(b) => {
+        x.set(x.get() + 1);
+        x.get() * b
+      }
+    };
+    assert_eq!(z, 18);
+}
diff --git a/src/test/ui/borrowck/borrowck-unsafe-static-mutable-borrows.rs b/src/test/ui/borrowck/borrowck-unsafe-static-mutable-borrows.rs
new file mode 100644
index 00000000000..adc7dfd541f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-unsafe-static-mutable-borrows.rs
@@ -0,0 +1,20 @@
+// run-pass
+
+// Test file taken from issue 45129 (https://github.com/rust-lang/rust/issues/45129)
+
+struct Foo { x: [usize; 2] }
+
+static mut SFOO: Foo = Foo { x: [23, 32] };
+
+impl Foo {
+    fn x(&mut self) -> &mut usize { &mut self.x[0] }
+}
+
+fn main() {
+    unsafe {
+        let sfoo: *mut Foo = &mut SFOO;
+        let x = (*sfoo).x();
+        (*sfoo).x[1] += 1;
+        *x += 1;
+    }
+}
diff --git a/src/test/ui/borrowck/borrowck-unused-mut-locals.rs b/src/test/ui/borrowck/borrowck-unused-mut-locals.rs
new file mode 100644
index 00000000000..fd0e346e2b4
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-unused-mut-locals.rs
@@ -0,0 +1,46 @@
+// run-pass
+#![deny(unused_mut)]
+
+#[derive(Debug)]
+struct A {}
+
+fn init_a() -> A {
+    A {}
+}
+
+#[derive(Debug)]
+struct B<'a> {
+    ed: &'a mut A,
+}
+
+fn init_b<'a>(ed: &'a mut A) -> B<'a> {
+    B { ed }
+}
+
+#[derive(Debug)]
+struct C<'a> {
+    pd: &'a mut B<'a>,
+}
+
+fn init_c<'a>(pd: &'a mut B<'a>) -> C<'a> {
+    C { pd }
+}
+
+#[derive(Debug)]
+struct D<'a> {
+    sd: &'a mut C<'a>,
+}
+
+fn init_d<'a>(sd: &'a mut C<'a>) -> D<'a> {
+    D { sd }
+}
+
+fn main() {
+    let mut a = init_a();
+    let mut b = init_b(&mut a);
+    let mut c = init_c(&mut b);
+
+    let d = init_d(&mut c);
+
+    println!("{:?}", d)
+}
diff --git a/src/test/ui/borrowck/issue-62007-assign-box.rs b/src/test/ui/borrowck/issue-62007-assign-box.rs
new file mode 100644
index 00000000000..f6fbea821b5
--- /dev/null
+++ b/src/test/ui/borrowck/issue-62007-assign-box.rs
@@ -0,0 +1,27 @@
+// run-pass
+
+// Issue #62007: assigning over a deref projection of a box (in this
+// case, `*list = n;`) should be able to kill all borrows of `*list`,
+// so that `*list` can be borrowed on the next iteration through the
+// loop.
+
+#![allow(dead_code)]
+
+struct List<T> {
+    value: T,
+    next: Option<Box<List<T>>>,
+}
+
+fn to_refs<T>(mut list: Box<&mut List<T>>) -> Vec<&mut T> {
+    let mut result = vec![];
+    loop {
+        result.push(&mut list.value);
+        if let Some(n) = list.next.as_mut() {
+            *list = n;
+        } else {
+            return result;
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/issue-62007-assign-field.rs b/src/test/ui/borrowck/issue-62007-assign-field.rs
new file mode 100644
index 00000000000..5b21c083816
--- /dev/null
+++ b/src/test/ui/borrowck/issue-62007-assign-field.rs
@@ -0,0 +1,26 @@
+// run-pass
+
+// Issue #62007: assigning over a field projection (`list.0 = n;` in
+// this case) should be able to kill all borrows of `list.0`, so that
+// `list.0` can be borrowed on the next iteration through the loop.
+
+#![allow(dead_code)]
+
+struct List<T> {
+    value: T,
+    next: Option<Box<List<T>>>,
+}
+
+fn to_refs<T>(mut list: (&mut List<T>,)) -> Vec<&mut T> {
+    let mut result = vec![];
+    loop {
+        result.push(&mut (list.0).value);
+        if let Some(n) = (list.0).next.as_mut() {
+            list.0 = n;
+        } else {
+            return result;
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/two-phase-baseline.rs b/src/test/ui/borrowck/two-phase-baseline.rs
new file mode 100644
index 00000000000..994dc823dfc
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-baseline.rs
@@ -0,0 +1,9 @@
+// run-pass
+
+// This is the "goto example" for why we want two phase borrows.
+
+fn main() {
+    let mut v = vec![0, 1, 2];
+    v.push(v.len());
+    assert_eq!(v, [0, 1, 2, 3]);
+}
diff --git a/src/test/ui/borrowck/two-phase-bin-ops.rs b/src/test/ui/borrowck/two-phase-bin-ops.rs
new file mode 100644
index 00000000000..1242ae307d3
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-bin-ops.rs
@@ -0,0 +1,35 @@
+// run-pass
+use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign};
+use std::ops::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign};
+
+struct A(i32);
+
+macro_rules! trivial_binop {
+    ($Trait:ident, $m:ident) => {
+        impl $Trait<i32> for A { fn $m(&mut self, rhs: i32) { self.0 = rhs; } }
+    }
+}
+
+trivial_binop!(AddAssign, add_assign);
+trivial_binop!(SubAssign, sub_assign);
+trivial_binop!(MulAssign, mul_assign);
+trivial_binop!(DivAssign, div_assign);
+trivial_binop!(RemAssign, rem_assign);
+trivial_binop!(BitAndAssign, bitand_assign);
+trivial_binop!(BitOrAssign, bitor_assign);
+trivial_binop!(BitXorAssign, bitxor_assign);
+trivial_binop!(ShlAssign, shl_assign);
+trivial_binop!(ShrAssign, shr_assign);
+
+fn main() {
+    let mut a = A(10);
+    a += a.0;
+    a -= a.0;
+    a *= a.0;
+    a /= a.0;
+    a &= a.0;
+    a |= a.0;
+    a ^= a.0;
+    a <<= a.0;
+    a >>= a.0;
+}
diff --git a/src/test/ui/borrowck/two-phase-control-flow-split-before-activation.rs b/src/test/ui/borrowck/two-phase-control-flow-split-before-activation.rs
new file mode 100644
index 00000000000..0b20e1945e6
--- /dev/null
+++ b/src/test/ui/borrowck/two-phase-control-flow-split-before-activation.rs
@@ -0,0 +1,15 @@
+// run-pass
+
+fn main() {
+    let mut a = 0;
+    let mut b = 0;
+    let p = if maybe() {
+        &mut a
+    } else {
+        &mut b
+    };
+    use_(p);
+}
+
+fn maybe() -> bool { false }
+fn use_<T>(_: T) { }