]> git.lizzy.rs Git - rust.git/commitdiff
Some new tests I added.
authorFelix S. Klock II <pnkfelix@pnkfx.org>
Thu, 11 Oct 2018 23:33:08 +0000 (01:33 +0200)
committerFelix S. Klock II <pnkfelix@pnkfx.org>
Wed, 17 Oct 2018 00:33:03 +0000 (02:33 +0200)
16 files changed:
src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.ast.stderr [new file with mode: 0644]
src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.nll.stderr [new file with mode: 0644]
src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs [new file with mode: 0644]
src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.ast.stderr [new file with mode: 0644]
src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.nll.stderr [new file with mode: 0644]
src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.rs [new file with mode: 0644]
src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.ast.stderr [new file with mode: 0644]
src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.nll.stderr [new file with mode: 0644]
src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.rs [new file with mode: 0644]
src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.ast.stderr [new file with mode: 0644]
src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.nll.stderr [new file with mode: 0644]
src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs [new file with mode: 0644]
src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs [new file with mode: 0644]
src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr [new file with mode: 0644]
src/test/ui/nll/issue-21232-partial-init-and-use.rs [new file with mode: 0644]
src/test/ui/nll/issue-21232-partial-init-and-use.stderr [new file with mode: 0644]

diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.ast.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.ast.stderr
new file mode 100644 (file)
index 0000000..d72cc20
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0381]: use of possibly uninitialized variable: `t.0`
+  --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:25:31
+   |
+LL |         println!("{:?} {:?}", t.0, t.1);
+   |                               ^^^ use of possibly uninitialized `t.0`
+
+error[E0381]: use of possibly uninitialized variable: `t.1`
+  --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:25:36
+   |
+LL |         println!("{:?} {:?}", t.0, t.1);
+   |                                    ^^^ use of possibly uninitialized `t.1`
+
+error[E0381]: use of possibly uninitialized variable: `u.0`
+  --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:35:31
+   |
+LL |         println!("{:?} {:?}", u.0, u.1);
+   |                               ^^^ use of possibly uninitialized `u.0`
+
+error[E0381]: use of possibly uninitialized variable: `u.1`
+  --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:35:36
+   |
+LL |         println!("{:?} {:?}", u.0, u.1);
+   |                                    ^^^ use of possibly uninitialized `u.1`
+
+error[E0381]: use of possibly uninitialized variable: `v.x`
+  --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:45:31
+   |
+LL |         println!("{:?} {:?}", v.x, v.y);
+   |                               ^^^ use of possibly uninitialized `v.x`
+
+error[E0381]: use of possibly uninitialized variable: `v.y`
+  --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:45:36
+   |
+LL |         println!("{:?} {:?}", v.x, v.y);
+   |                                    ^^^ use of possibly uninitialized `v.y`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.nll.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.nll.stderr
new file mode 100644 (file)
index 0000000..ebc6c7f
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0381]: assign to part of possibly uninitialized variable: `t`
+  --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:22:9
+   |
+LL |         t.0 = S(1);
+   |         ^^^^^^^^^^ use of possibly uninitialized `t`
+
+error[E0381]: assign to part of possibly uninitialized variable: `u`
+  --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:32:9
+   |
+LL |         u.0 = S(1);
+   |         ^^^^^^^^^^ use of possibly uninitialized `u`
+
+error[E0381]: assign to part of possibly uninitialized variable: `v`
+  --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:42:9
+   |
+LL |         v.x = S(1);
+   |         ^^^^^^^^^^ use of possibly uninitialized `v`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs
new file mode 100644 (file)
index 0000000..4358e8e
--- /dev/null
@@ -0,0 +1,49 @@
+// revisions: ast nll
+
+// Since we are testing nll migration explicitly as a separate
+// revision, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
+//[ast]compile-flags: -Z borrowck=ast
+//[nll]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+
+#![warn(unused)]
+#[derive(Debug)]
+struct S(i32);
+
+type Tuple = (S, i32);
+struct Tpair(S, i32);
+struct Spair { x: S, y: i32 }
+
+fn main() {
+    {
+        let mut t: Tuple;
+        t.0 = S(1);
+        //[nll]~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+        t.1 = 2;
+        println!("{:?} {:?}", t.0, t.1);
+        //[ast]~^ ERROR use of possibly uninitialized variable: `t.0` [E0381]
+        //[ast]~| ERROR use of possibly uninitialized variable: `t.1` [E0381]
+    }
+
+    {
+        let mut u: Tpair;
+        u.0 = S(1);
+        //[nll]~^ ERROR assign to part of possibly uninitialized variable: `u` [E0381]
+        u.1 = 2;
+        println!("{:?} {:?}", u.0, u.1);
+        //[ast]~^ ERROR use of possibly uninitialized variable: `u.0` [E0381]
+        //[ast]~| ERROR use of possibly uninitialized variable: `u.1` [E0381]
+    }
+
+    {
+        let mut v: Spair;
+        v.x = S(1);
+        //[nll]~^ ERROR assign to part of possibly uninitialized variable: `v` [E0381]
+        v.y = 2;
+        println!("{:?} {:?}", v.x, v.y);
+        //[ast]~^ ERROR use of possibly uninitialized variable: `v.x` [E0381]
+        //[ast]~| ERROR use of possibly uninitialized variable: `v.y` [E0381]
+    }
+}
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.ast.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.ast.stderr
new file mode 100644 (file)
index 0000000..e3b5341
--- /dev/null
@@ -0,0 +1,69 @@
+error[E0382]: use of moved value: `t.0`
+  --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:25:31
+   |
+LL |         drop(t);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", t.0, t.1);
+   |                               ^^^ value used here after move
+   |
+   = note: move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `t.1`
+  --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:25:36
+   |
+LL |         drop(t);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", t.0, t.1);
+   |                                    ^^^ value used here after move
+   |
+   = note: move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `u.0`
+  --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:33:31
+   |
+LL |         drop(u);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", u.0, u.1);
+   |                               ^^^ value used here after move
+   |
+   = note: move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `u.1`
+  --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:33:36
+   |
+LL |         drop(u);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", u.0, u.1);
+   |                                    ^^^ value used here after move
+   |
+   = note: move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `v.x`
+  --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:41:31
+   |
+LL |         drop(v);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", v.x, v.y);
+   |                               ^^^ value used here after move
+   |
+   = note: move occurs because `v` has type `Spair`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `v.y`
+  --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:41:36
+   |
+LL |         drop(v);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", v.x, v.y);
+   |                                    ^^^ value used here after move
+   |
+   = note: move occurs because `v` has type `Spair`, which does not implement the `Copy` trait
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.nll.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.nll.stderr
new file mode 100644 (file)
index 0000000..001ed59
--- /dev/null
@@ -0,0 +1,33 @@
+error[E0382]: assign to part of moved value: `t`
+  --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:23:9
+   |
+LL |         drop(t);
+   |              - value moved here
+LL |         t.0 = S(1);
+   |         ^^^^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait
+
+error[E0382]: assign to part of moved value: `u`
+  --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:31:9
+   |
+LL |         drop(u);
+   |              - value moved here
+LL |         u.0 = S(1);
+   |         ^^^^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait
+
+error[E0382]: assign to part of moved value: `v`
+  --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:39:9
+   |
+LL |         drop(v);
+   |              - value moved here
+LL |         v.x = S(1);
+   |         ^^^^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `v` has type `Spair`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.rs b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.rs
new file mode 100644 (file)
index 0000000..b6339c4
--- /dev/null
@@ -0,0 +1,43 @@
+// revisions: ast nll
+
+// Since we are testing nll migration explicitly as a separate
+// revision, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
+//[ast]compile-flags: -Z borrowck=ast
+//[nll]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+
+#![warn(unused)]
+#[derive(Debug)]
+struct S(i32);
+
+type Tuple = (S, i32);
+struct Tpair(S, i32);
+struct Spair { x: S, y: i32 }
+
+fn main() {
+    {
+        let mut t: Tuple = (S(0), 0);
+        drop(t);
+        t.0 = S(1);
+        t.1 = 2;
+        println!("{:?} {:?}", t.0, t.1);
+    }
+
+    {
+        let mut u: Tpair = Tpair(S(0), 0);
+        drop(u);
+        u.0 = S(1);
+        u.1 = 2;
+        println!("{:?} {:?}", u.0, u.1);
+    }
+
+    {
+        let mut v: Spair = Spair { x: S(0), y: 0 };
+        drop(v);
+        v.x = S(1);
+        v.y = 2;
+        println!("{:?} {:?}", v.x, v.y);
+    }
+}
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.ast.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.ast.stderr
new file mode 100644 (file)
index 0000000..565272a
--- /dev/null
@@ -0,0 +1,124 @@
+error[E0594]: cannot assign to field `t.0` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:23:9
+   |
+LL |         let t: Tuple = (S(0), 0);
+   |             - help: make this binding mutable: `mut t`
+LL |         drop(t);
+LL |         t.0 = S(1);
+   |         ^^^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `t.1` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:27:9
+   |
+LL |         let t: Tuple = (S(0), 0);
+   |             - help: make this binding mutable: `mut t`
+...
+LL |         t.1 = 2;
+   |         ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `u.0` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:38:9
+   |
+LL |         let u: Tpair = Tpair(S(0), 0);
+   |             - help: make this binding mutable: `mut u`
+LL |         drop(u);
+LL |         u.0 = S(1);
+   |         ^^^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `u.1` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:42:9
+   |
+LL |         let u: Tpair = Tpair(S(0), 0);
+   |             - help: make this binding mutable: `mut u`
+...
+LL |         u.1 = 2;
+   |         ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `v.x` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:53:9
+   |
+LL |         let v: Spair = Spair { x: S(0), y: 0 };
+   |             - help: make this binding mutable: `mut v`
+LL |         drop(v);
+LL |         v.x = S(1);
+   |         ^^^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `v.y` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:57:9
+   |
+LL |         let v: Spair = Spair { x: S(0), y: 0 };
+   |             - help: make this binding mutable: `mut v`
+...
+LL |         v.y = 2;
+   |         ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0382]: use of moved value: `t.0`
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:30:31
+   |
+LL |         drop(t);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", t.0, t.1);
+   |                               ^^^ value used here after move
+   |
+   = note: move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `t.1`
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:30:36
+   |
+LL |         drop(t);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", t.0, t.1);
+   |                                    ^^^ value used here after move
+   |
+   = note: move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `u.0`
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:45:31
+   |
+LL |         drop(u);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", u.0, u.1);
+   |                               ^^^ value used here after move
+   |
+   = note: move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `u.1`
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:45:36
+   |
+LL |         drop(u);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", u.0, u.1);
+   |                                    ^^^ value used here after move
+   |
+   = note: move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `v.x`
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:60:31
+   |
+LL |         drop(v);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", v.x, v.y);
+   |                               ^^^ value used here after move
+   |
+   = note: move occurs because `v` has type `Spair`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `v.y`
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:60:36
+   |
+LL |         drop(v);
+   |              - value moved here
+...
+LL |         println!("{:?} {:?}", v.x, v.y);
+   |                                    ^^^ value used here after move
+   |
+   = note: move occurs because `v` has type `Spair`, which does not implement the `Copy` trait
+
+error: aborting due to 12 previous errors
+
+Some errors occurred: E0382, E0594.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.nll.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.nll.stderr
new file mode 100644 (file)
index 0000000..d35d005
--- /dev/null
@@ -0,0 +1,88 @@
+error[E0594]: cannot assign to `t.0`, as `t` is not declared as mutable
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:23:9
+   |
+LL |         let t: Tuple = (S(0), 0);
+   |             - help: consider changing this to be mutable: `mut t`
+LL |         drop(t);
+LL |         t.0 = S(1);
+   |         ^^^^^^^^^^ cannot assign
+
+error[E0382]: assign to part of moved value: `t`
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:23:9
+   |
+LL |         drop(t);
+   |              - value moved here
+LL |         t.0 = S(1);
+   |         ^^^^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait
+
+error[E0594]: cannot assign to `t.1`, as `t` is not declared as mutable
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:27:9
+   |
+LL |         let t: Tuple = (S(0), 0);
+   |             - help: consider changing this to be mutable: `mut t`
+...
+LL |         t.1 = 2;
+   |         ^^^^^^^ cannot assign
+
+error[E0594]: cannot assign to `u.0`, as `u` is not declared as mutable
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:38:9
+   |
+LL |         let u: Tpair = Tpair(S(0), 0);
+   |             - help: consider changing this to be mutable: `mut u`
+LL |         drop(u);
+LL |         u.0 = S(1);
+   |         ^^^^^^^^^^ cannot assign
+
+error[E0382]: assign to part of moved value: `u`
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:38:9
+   |
+LL |         drop(u);
+   |              - value moved here
+LL |         u.0 = S(1);
+   |         ^^^^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait
+
+error[E0594]: cannot assign to `u.1`, as `u` is not declared as mutable
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:42:9
+   |
+LL |         let u: Tpair = Tpair(S(0), 0);
+   |             - help: consider changing this to be mutable: `mut u`
+...
+LL |         u.1 = 2;
+   |         ^^^^^^^ cannot assign
+
+error[E0594]: cannot assign to `v.x`, as `v` is not declared as mutable
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:53:9
+   |
+LL |         let v: Spair = Spair { x: S(0), y: 0 };
+   |             - help: consider changing this to be mutable: `mut v`
+LL |         drop(v);
+LL |         v.x = S(1);
+   |         ^^^^^^^^^^ cannot assign
+
+error[E0382]: assign to part of moved value: `v`
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:53:9
+   |
+LL |         drop(v);
+   |              - value moved here
+LL |         v.x = S(1);
+   |         ^^^^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `v` has type `Spair`, which does not implement the `Copy` trait
+
+error[E0594]: cannot assign to `v.y`, as `v` is not declared as mutable
+  --> $DIR/issue-54499-field-mutation-of-moved-out.rs:57:9
+   |
+LL |         let v: Spair = Spair { x: S(0), y: 0 };
+   |             - help: consider changing this to be mutable: `mut v`
+...
+LL |         v.y = 2;
+   |         ^^^^^^^ cannot assign
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0382, E0594.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.rs b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.rs
new file mode 100644 (file)
index 0000000..b19dcd6
--- /dev/null
@@ -0,0 +1,64 @@
+// revisions: ast nll
+
+// Since we are testing nll migration explicitly as a separate
+// revision, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
+//[ast]compile-flags: -Z borrowck=ast
+//[nll]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+
+#![warn(unused)]
+#[derive(Debug)]
+struct S(i32);
+
+type Tuple = (S, i32);
+struct Tpair(S, i32);
+struct Spair { x: S, y: i32 }
+
+fn main() {
+    {
+        let t: Tuple = (S(0), 0);
+        drop(t);
+        t.0 = S(1);
+        //[ast]~^ ERROR cannot assign to field `t.0` of immutable binding [E0594]
+        //[nll]~^^ ERROR assign to part of moved value: `t` [E0382]
+        //[nll]~| ERROR cannot assign to `t.0`, as `t` is not declared as mutable [E0594]
+        t.1 = 2;
+        //[ast]~^ ERROR cannot assign to field `t.1` of immutable binding [E0594]
+        //[nll]~^^ ERROR cannot assign to `t.1`, as `t` is not declared as mutable [E0594]
+        println!("{:?} {:?}", t.0, t.1);
+        //[ast]~^ ERROR use of moved value: `t.0` [E0382]
+        //[ast]~| ERROR use of moved value: `t.1` [E0382]
+    }
+
+    {
+        let u: Tpair = Tpair(S(0), 0);
+        drop(u);
+        u.0 = S(1);
+        //[ast]~^ ERROR cannot assign to field `u.0` of immutable binding [E0594]
+        //[nll]~^^ ERROR assign to part of moved value: `u` [E0382]
+        //[nll]~| ERROR cannot assign to `u.0`, as `u` is not declared as mutable [E0594]
+        u.1 = 2;
+        //[ast]~^ ERROR cannot assign to field `u.1` of immutable binding [E0594]
+        //[nll]~^^ ERROR cannot assign to `u.1`, as `u` is not declared as mutable [E0594]
+        println!("{:?} {:?}", u.0, u.1);
+        //[ast]~^ ERROR use of moved value: `u.0` [E0382]
+        //[ast]~| ERROR use of moved value: `u.1` [E0382]
+    }
+
+    {
+        let v: Spair = Spair { x: S(0), y: 0 };
+        drop(v);
+        v.x = S(1);
+        //[ast]~^ ERROR cannot assign to field `v.x` of immutable binding [E0594]
+        //[nll]~^^ ERROR assign to part of moved value: `v` [E0382]
+        //[nll]~| ERROR cannot assign to `v.x`, as `v` is not declared as mutable [E0594]
+        v.y = 2;
+        //[ast]~^ ERROR cannot assign to field `v.y` of immutable binding [E0594]
+        //[nll]~^^ ERROR cannot assign to `v.y`, as `v` is not declared as mutable [E0594]
+        println!("{:?} {:?}", v.x, v.y);
+        //[ast]~^ ERROR use of moved value: `v.x` [E0382]
+        //[ast]~| ERROR use of moved value: `v.y` [E0382]
+    }
+}
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.ast.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.ast.stderr
new file mode 100644 (file)
index 0000000..ea6b63b
--- /dev/null
@@ -0,0 +1,91 @@
+error[E0594]: cannot assign to field `t.0` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:22:9
+   |
+LL |         let t: Tuple;
+   |             - help: make this binding mutable: `mut t`
+LL |         t.0 = S(1);
+   |         ^^^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `t.1` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:25:9
+   |
+LL |         let t: Tuple;
+   |             - help: make this binding mutable: `mut t`
+...
+LL |         t.1 = 2;
+   |         ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `u.0` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:34:9
+   |
+LL |         let u: Tpair;
+   |             - help: make this binding mutable: `mut u`
+LL |         u.0 = S(1);
+   |         ^^^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `u.1` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:37:9
+   |
+LL |         let u: Tpair;
+   |             - help: make this binding mutable: `mut u`
+...
+LL |         u.1 = 2;
+   |         ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `v.x` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:46:9
+   |
+LL |         let v: Spair;
+   |             - help: make this binding mutable: `mut v`
+LL |         v.x = S(1);
+   |         ^^^^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0594]: cannot assign to field `v.y` of immutable binding
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:49:9
+   |
+LL |         let v: Spair;
+   |             - help: make this binding mutable: `mut v`
+...
+LL |         v.y = 2;
+   |         ^^^^^^^ cannot mutably borrow field of immutable binding
+
+error[E0381]: use of possibly uninitialized variable: `t.0`
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:27:31
+   |
+LL |         println!("{:?} {:?}", t.0, t.1);
+   |                               ^^^ use of possibly uninitialized `t.0`
+
+error[E0381]: use of possibly uninitialized variable: `t.1`
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:27:36
+   |
+LL |         println!("{:?} {:?}", t.0, t.1);
+   |                                    ^^^ use of possibly uninitialized `t.1`
+
+error[E0381]: use of possibly uninitialized variable: `u.0`
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:39:31
+   |
+LL |         println!("{:?} {:?}", u.0, u.1);
+   |                               ^^^ use of possibly uninitialized `u.0`
+
+error[E0381]: use of possibly uninitialized variable: `u.1`
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:39:36
+   |
+LL |         println!("{:?} {:?}", u.0, u.1);
+   |                                    ^^^ use of possibly uninitialized `u.1`
+
+error[E0381]: use of possibly uninitialized variable: `v.x`
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:51:31
+   |
+LL |         println!("{:?} {:?}", v.x, v.y);
+   |                               ^^^ use of possibly uninitialized `v.x`
+
+error[E0381]: use of possibly uninitialized variable: `v.y`
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:51:36
+   |
+LL |         println!("{:?} {:?}", v.x, v.y);
+   |                                    ^^^ use of possibly uninitialized `v.y`
+
+error: aborting due to 12 previous errors
+
+Some errors occurred: E0381, E0594.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.nll.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.nll.stderr
new file mode 100644 (file)
index 0000000..3dc2b5b
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0381]: assign to part of possibly uninitialized variable: `t`
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:22:9
+   |
+LL |         t.0 = S(1);
+   |         ^^^^^^^^^^ use of possibly uninitialized `t`
+
+error[E0381]: assign to part of possibly uninitialized variable: `u`
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:34:9
+   |
+LL |         u.0 = S(1);
+   |         ^^^^^^^^^^ use of possibly uninitialized `u`
+
+error[E0381]: assign to part of possibly uninitialized variable: `v`
+  --> $DIR/issue-54499-field-mutation-of-never-init.rs:46:9
+   |
+LL |         v.x = S(1);
+   |         ^^^^^^^^^^ use of possibly uninitialized `v`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs
new file mode 100644 (file)
index 0000000..03eb962
--- /dev/null
@@ -0,0 +1,55 @@
+// revisions: ast nll
+
+// Since we are testing nll migration explicitly as a separate
+// revision, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
+//[ast]compile-flags: -Z borrowck=ast
+//[nll]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+
+#![warn(unused)]
+#[derive(Debug)]
+struct S(i32);
+
+type Tuple = (S, i32);
+struct Tpair(S, i32);
+struct Spair { x: S, y: i32 }
+
+fn main() {
+    {
+        let t: Tuple;
+        t.0 = S(1);
+        //[ast]~^ ERROR cannot assign to field `t.0` of immutable binding [E0594]
+        //[nll]~^^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+        t.1 = 2;
+        //[ast]~^ ERROR cannot assign to field `t.1` of immutable binding [E0594]
+        println!("{:?} {:?}", t.0, t.1);
+        //[ast]~^ ERROR use of possibly uninitialized variable: `t.0` [E0381]
+        //[ast]~| ERROR use of possibly uninitialized variable: `t.1` [E0381]
+    }
+
+    {
+        let u: Tpair;
+        u.0 = S(1);
+        //[ast]~^ ERROR cannot assign to field `u.0` of immutable binding [E0594]
+        //[nll]~^^ ERROR assign to part of possibly uninitialized variable: `u` [E0381]
+        u.1 = 2;
+        //[ast]~^ ERROR cannot assign to field `u.1` of immutable binding [E0594]
+        println!("{:?} {:?}", u.0, u.1);
+        //[ast]~^ ERROR use of possibly uninitialized variable: `u.0` [E0381]
+        //[ast]~| ERROR use of possibly uninitialized variable: `u.1` [E0381]
+    }
+
+    {
+        let v: Spair;
+        v.x = S(1);
+        //[ast]~^ ERROR cannot assign to field `v.x` of immutable binding [E0594]
+        //[nll]~^^ ERROR assign to part of possibly uninitialized variable: `v` [E0381]
+        v.y = 2;
+        //[ast]~^ ERROR cannot assign to field `v.y` of immutable binding [E0594]
+        println!("{:?} {:?}", v.x, v.y);
+        //[ast]~^ ERROR use of possibly uninitialized variable: `v.x` [E0381]
+        //[ast]~| ERROR use of possibly uninitialized variable: `v.y` [E0381]
+    }
+}
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs
new file mode 100644 (file)
index 0000000..abafd33
--- /dev/null
@@ -0,0 +1,66 @@
+// This test enumerates various cases of interest where a ADT or tuple is
+// partially initialized and then used in some way that is wrong *even*
+// after rust-lang/rust#54987 is implemented.
+//
+// See rust-lang/rust#21232, rust-lang/rust#54986, and rust-lang/rust#54987.
+//
+// See issue-21232-partial-init-and-use.rs for cases of tests that are
+// meant to compile and run successfully once rust-lang/rust#54987 is
+// implemented.
+
+#![feature(nll)]
+
+struct D {
+    x: u32,
+    s: S,
+}
+
+struct S {
+    y: u32,
+    z: u32,
+}
+
+
+impl Drop for D {
+    fn drop(&mut self) { }
+}
+
+fn cannot_partially_init_adt_with_drop() {
+    let d: D;
+    d.x = 10;
+    //~^ ERROR assign of possibly uninitialized variable: `d` [E0381]
+}
+
+fn cannot_partially_init_mutable_adt_with_drop() {
+    let mut d: D;
+    d.x = 10;
+    //~^ ERROR assign of possibly uninitialized variable: `d` [E0381]
+}
+
+fn cannot_partially_reinit_adt_with_drop() {
+    let mut d = D { x: 0, s: S{ y: 0, z: 0 } };
+    drop(d);
+    d.x = 10;
+    //~^ ERROR assign of moved value: `d` [E0382]
+}
+
+fn cannot_partially_init_inner_adt_via_outer_with_drop() {
+    let d: D;
+    d.s.y = 20;
+    //~^ ERROR assign to part of possibly uninitialized variable: `d` [E0381]
+}
+
+fn cannot_partially_init_inner_adt_via_mutable_outer_with_drop() {
+    let mut d: D;
+    d.s.y = 20;
+    //~^ ERROR assign to part of possibly uninitialized variable: `d` [E0381]
+}
+
+fn cannot_partially_reinit_inner_adt_via_outer_with_drop() {
+    let mut d = D { x: 0, s: S{ y: 0, z: 0} };
+    drop(d);
+    d.s.y = 20;
+    //~^ ERROR assign to part of moved value: `d` [E0382]
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr
new file mode 100644 (file)
index 0000000..e29c447
--- /dev/null
@@ -0,0 +1,48 @@
+error[E0381]: assign of possibly uninitialized variable: `d`
+  --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:30:5
+   |
+LL |     d.x = 10;
+   |     ^^^^^^^^ use of possibly uninitialized `d`
+
+error[E0381]: assign of possibly uninitialized variable: `d`
+  --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:36:5
+   |
+LL |     d.x = 10;
+   |     ^^^^^^^^ use of possibly uninitialized `d`
+
+error[E0382]: assign of moved value: `d`
+  --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:43:5
+   |
+LL |     drop(d);
+   |          - value moved here
+LL |     d.x = 10;
+   |     ^^^^^^^^ value assigned here after move
+   |
+   = note: move occurs because `d` has type `D`, which does not implement the `Copy` trait
+
+error[E0381]: assign to part of possibly uninitialized variable: `d`
+  --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:49:5
+   |
+LL |     d.s.y = 20;
+   |     ^^^^^^^^^^ use of possibly uninitialized `d.s`
+
+error[E0381]: assign to part of possibly uninitialized variable: `d`
+  --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:55:5
+   |
+LL |     d.s.y = 20;
+   |     ^^^^^^^^^^ use of possibly uninitialized `d.s`
+
+error[E0382]: assign to part of moved value: `d`
+  --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:62:5
+   |
+LL |     drop(d);
+   |          - value moved here
+LL |     d.s.y = 20;
+   |     ^^^^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `d` has type `D`, which does not implement the `Copy` trait
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0381, E0382.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.rs b/src/test/ui/nll/issue-21232-partial-init-and-use.rs
new file mode 100644 (file)
index 0000000..e3ae4c0
--- /dev/null
@@ -0,0 +1,311 @@
+// This test enumerates various cases of interest for partial
+// [re]initialization of ADTs and tuples.
+//
+// See rust-lang/rust#21232, rust-lang/rust#54986, and rust-lang/rust#54987.
+//
+// All of tests in this file are expected to change from being
+// rejected, at least under NLL (by rust-lang/rust#54986) to being
+// **accepted** when rust-lang/rust#54987 is implemented.
+// (That's why there are assertions in the code.)
+//
+// See issue-21232-partial-init-and-erroneous-use.rs for cases of
+// tests that are meant to continue failing to compile once
+// rust-lang/rust#54987 is implemented.
+
+#![feature(nll)]
+
+struct S<Y> {
+    x: u32,
+
+    // Note that even though `y` may implement `Drop`, under #54987 we
+    // will still allow partial initialization of `S` itself.
+    y: Y,
+}
+
+enum Void { }
+
+type B = Box<u32>;
+
+impl S<B> { fn new() -> Self { S { x: 0, y: Box::new(0) } } }
+
+fn borrow_s(s: &S<B>) { assert_eq!(s.x, 10); assert_eq!(*s.y, 20); }
+fn move_s(s: S<B>) {  assert_eq!(s.x, 10); assert_eq!(*s.y, 20); }
+fn borrow_field(x: &u32) { assert_eq!(*x, 10); }
+
+type T = (u32, B);
+type Tvoid = (u32, Void);
+
+fn borrow_t(t: &T) { assert_eq!(t.0, 10); assert_eq!(*t.1, 20); }
+fn move_t(t: T) {  assert_eq!(t.0, 10); assert_eq!(*t.1, 20); }
+
+struct Q<F> {
+    v: u32,
+    r: R<F>,
+}
+
+struct R<F> {
+    w: u32,
+    f: F,
+}
+
+impl<F> Q<F> { fn new(f: F) -> Self { Q { v: 0, r: R::new(f) } } }
+impl<F> R<F> { fn new(f: F) -> Self { R { w: 0, f } } }
+
+// Axes to cover:
+// * local/field: Is the structure in a local or a field
+// * fully/partial/void: Are we fully initializing it before using any part?
+//                       Is whole type empty due to a void component?
+// * init/reinit: First initialization, or did we previously inititalize and then move out?
+// * struct/tuple: Is this a struct or a (X, Y).
+//
+// As a shorthand for the cases above, adding a numeric summary to
+// each test's fn name to denote each point on each axis.
+//
+// E.g. 1000 = field fully init struct; 0211 = local void reinit tuple
+
+// It got pretty monotonous writing the same code over and over, and I
+// feared I would forget details. So I abstracted some desiderata into
+// macros. But I left the initialization code inline, because that's
+// where the errors for #54986 will be emited.
+
+macro_rules! use_fully {
+    (struct $s:expr) => { {
+        borrow_field(& $s.x );
+        borrow_s(& $s );
+        move_s( $s );
+    } };
+
+    (tuple $t:expr) => { {
+        borrow_field(& $t.0 );
+        borrow_t(& $t );
+        move_t( $t );
+    } }
+}
+
+macro_rules! use_part {
+    (struct $s:expr) => { {
+        borrow_field(& $s.x );
+        match $s { S { ref x, y: _ } => { borrow_field(x); } }
+    } };
+
+    (tuple $t:expr) => { {
+        borrow_field(& $t.0 );
+        match $t { (ref x, _) => { borrow_field(x); } }
+    } }
+}
+
+fn test_0000_local_fully_init_and_use_struct() {
+    let s: S<B>;
+    s.x = 10; s.y = Box::new(20);
+    //~^ ERROR assign to part of possibly uninitialized variable: `s` [E0381]
+    use_fully!(struct s);
+}
+
+fn test_0001_local_fully_init_and_use_tuple() {
+    let t: T;
+    t.0 = 10; t.1 = Box::new(20);
+    //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+    use_fully!(tuple t);
+}
+
+fn test_0010_local_fully_reinit_and_use_struct() {
+    let mut s: S<B> = S::new(); drop(s);
+    s.x = 10; s.y = Box::new(20);
+    //~^ ERROR assign to part of moved value: `s` [E0382]
+    use_fully!(struct s);
+}
+
+fn test_0011_local_fully_reinit_and_use_tuple() {
+    let mut t: T = (0, Box::new(0)); drop(t);
+    t.0 = 10; t.1 = Box::new(20);
+    //~^ ERROR assign to part of moved value: `t` [E0382]
+    use_fully!(tuple t);
+}
+
+fn test_0100_local_partial_init_and_use_struct() {
+    let s: S<B>;
+    s.x = 10;
+    //~^ ERROR assign to part of possibly uninitialized variable: `s` [E0381]
+    use_part!(struct s);
+}
+
+fn test_0101_local_partial_init_and_use_tuple() {
+    let t: T;
+    t.0 = 10;
+    //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+    use_part!(tuple t);
+}
+
+fn test_0110_local_partial_reinit_and_use_struct() {
+    let mut s: S<B> = S::new(); drop(s);
+    s.x = 10;
+    //~^ ERROR assign to part of moved value: `s` [E0382]
+    use_part!(struct s);
+}
+
+fn test_0111_local_partial_reinit_and_use_tuple() {
+    let mut t: T = (0, Box::new(0)); drop(t);
+    t.0 = 10;
+    //~^ ERROR assign to part of moved value: `t` [E0382]
+    use_part!(tuple t);
+}
+
+fn test_0200_local_void_init_and_use_struct() {
+    let s: S<Void>;
+    s.x = 10;
+    //~^ ERROR assign to part of possibly uninitialized variable: `s` [E0381]
+    use_part!(struct s);
+}
+
+fn test_0201_local_void_init_and_use_tuple() {
+    let t: Tvoid;
+    t.0 = 10;
+    //~^ ERROR assign to part of possibly uninitialized variable: `t` [E0381]
+    use_part!(tuple t);
+}
+
+// NOTE: uniform structure of tests here makes n21n (aka combining
+// Void with Reinit) an (even more) senseless case, as we cannot
+// safely create initial instance containing Void to move out of and
+// then reinitialize. While I was tempted to sidestep this via some
+// unsafe code (eek), lets just instead not encode such tests.
+
+// fn test_0210_local_void_reinit_and_use_struct() { unimplemented!() }
+// fn test_0211_local_void_reinit_and_use_tuple() { unimplemented!() }
+
+fn test_1000_field_fully_init_and_use_struct() {
+    let q: Q<S<B>>;
+    q.r.f.x = 10; q.r.f.y = Box::new(20);
+    //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
+    use_fully!(struct q.r.f);
+}
+
+fn test_1001_field_fully_init_and_use_tuple() {
+    let q: Q<T>;
+    q.r.f.0 = 10; q.r.f.1 = Box::new(20);
+    //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
+    use_fully!(tuple q.r.f);
+}
+
+fn test_1010_field_fully_reinit_and_use_struct() {
+    let mut q: Q<S<B>> = Q::new(S::new()); drop(q.r);
+    q.r.f.x = 10; q.r.f.y = Box::new(20);
+    //~^ ERROR assign to part of moved value: `q.r` [E0382]
+    use_fully!(struct q.r.f);
+}
+
+fn test_1011_field_fully_reinit_and_use_tuple() {
+    let mut q: Q<T> = Q::new((0, Box::new(0))); drop(q.r);
+    q.r.f.0 = 10; q.r.f.1 = Box::new(20);
+    //~^ ERROR assign to part of moved value: `q.r` [E0382]
+    use_fully!(tuple q.r.f);
+}
+
+fn test_1100_field_partial_init_and_use_struct() {
+    let q: Q<S<B>>;
+    q.r.f.x = 10;
+    //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
+    use_part!(struct q.r.f);
+}
+
+fn test_1101_field_partial_init_and_use_tuple() {
+    let q: Q<T>;
+    q.r.f.0 = 10;
+    //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
+    use_part!(tuple q.r.f);
+}
+
+fn test_1110_field_partial_reinit_and_use_struct() {
+    let mut q: Q<S<B>> = Q::new(S::new()); drop(q.r);
+    q.r.f.x = 10;
+    //~^ ERROR assign to part of moved value: `q.r` [E0382]
+    use_part!(struct q.r.f);
+}
+
+fn test_1111_field_partial_reinit_and_use_tuple() {
+    let mut q: Q<T> = Q::new((0, Box::new(0))); drop(q.r);
+    q.r.f.0 = 10;
+    //~^ ERROR assign to part of moved value: `q.r` [E0382]
+    use_part!(tuple q.r.f);
+}
+
+fn test_1200_field_void_init_and_use_struct() {
+    let mut q: Q<S<Void>>;
+    q.r.f.x = 10;
+    //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
+    use_part!(struct q.r.f);
+}
+
+fn test_1201_field_void_init_and_use_tuple() {
+    let mut q: Q<Tvoid>;
+    q.r.f.0 = 10;
+    //~^ ERROR assign to part of possibly uninitialized variable: `q` [E0381]
+    use_part!(tuple q.r.f);
+}
+
+// See NOTE abve.
+
+// fn test_1210_field_void_reinit_and_use_struct() { unimplemented!() }
+// fn test_1211_field_void_reinit_and_use_tuple() { unimplemented!() }
+
+// The below are some additional cases of interest that have been
+// transcribed from other bugs based on old erroneous codegen when we
+// encountered partial writes.
+
+fn issue_26996() {
+    let mut c = (1, "".to_owned());
+    match c {
+        c2 => {
+            c.0 = 2; //~ ERROR assign to part of moved value
+            assert_eq!(c2.0, 1);
+        }
+    }
+}
+
+fn issue_27021() {
+    let mut c = (1, (1, "".to_owned()));
+    match c {
+        c2 => {
+            (c.1).0 = 2; //~ ERROR assign to part of moved value
+            assert_eq!((c2.1).0, 1);
+        }
+    }
+
+    let mut c = (1, (1, (1, "".to_owned())));
+    match c.1 {
+        c2 => {
+            ((c.1).1).0 = 3; //~ ERROR assign to part of moved value
+            assert_eq!((c2.1).0, 1);
+        }
+    }
+}
+
+fn main() {
+    test_0000_local_fully_init_and_use_struct();
+    test_0001_local_fully_init_and_use_tuple();
+    test_0010_local_fully_reinit_and_use_struct();
+    test_0011_local_fully_reinit_and_use_tuple();
+    test_0100_local_partial_init_and_use_struct();
+    test_0101_local_partial_init_and_use_tuple();
+    test_0110_local_partial_reinit_and_use_struct();
+    test_0111_local_partial_reinit_and_use_tuple();
+    test_0200_local_void_init_and_use_struct();
+    test_0201_local_void_init_and_use_tuple();
+    // test_0210_local_void_reinit_and_use_struct();
+    // test_0211_local_void_reinit_and_use_tuple();
+    test_1000_field_fully_init_and_use_struct();
+    test_1001_field_fully_init_and_use_tuple();
+    test_1010_field_fully_reinit_and_use_struct();
+    test_1011_field_fully_reinit_and_use_tuple();
+    test_1100_field_partial_init_and_use_struct();
+    test_1101_field_partial_init_and_use_tuple();
+    test_1110_field_partial_reinit_and_use_struct();
+    test_1111_field_partial_reinit_and_use_tuple();
+    test_1200_field_void_init_and_use_struct();
+    test_1201_field_void_init_and_use_tuple();
+    // test_1210_field_void_reinit_and_use_struct();
+    // test_1211_field_void_reinit_and_use_tuple();
+
+    issue_26996();
+    issue_27021();
+}
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr
new file mode 100644 (file)
index 0000000..aec7f67
--- /dev/null
@@ -0,0 +1,186 @@
+error[E0381]: assign to part of possibly uninitialized variable: `s`
+  --> $DIR/issue-21232-partial-init-and-use.rs:99:5
+   |
+LL |     s.x = 10; s.y = Box::new(20);
+   |     ^^^^^^^^ use of possibly uninitialized `s`
+
+error[E0381]: assign to part of possibly uninitialized variable: `t`
+  --> $DIR/issue-21232-partial-init-and-use.rs:106:5
+   |
+LL |     t.0 = 10; t.1 = Box::new(20);
+   |     ^^^^^^^^ use of possibly uninitialized `t`
+
+error[E0382]: assign to part of moved value: `s`
+  --> $DIR/issue-21232-partial-init-and-use.rs:113:5
+   |
+LL |     let mut s: S<B> = S::new(); drop(s);
+   |                                      - value moved here
+LL |     s.x = 10; s.y = Box::new(20);
+   |     ^^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `s` has type `S<std::boxed::Box<u32>>`, which does not implement the `Copy` trait
+
+error[E0382]: assign to part of moved value: `t`
+  --> $DIR/issue-21232-partial-init-and-use.rs:120:5
+   |
+LL |     let mut t: T = (0, Box::new(0)); drop(t);
+   |                                           - value moved here
+LL |     t.0 = 10; t.1 = Box::new(20);
+   |     ^^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `t` has type `(u32, std::boxed::Box<u32>)`, which does not implement the `Copy` trait
+
+error[E0381]: assign to part of possibly uninitialized variable: `s`
+  --> $DIR/issue-21232-partial-init-and-use.rs:127:5
+   |
+LL |     s.x = 10;
+   |     ^^^^^^^^ use of possibly uninitialized `s`
+
+error[E0381]: assign to part of possibly uninitialized variable: `t`
+  --> $DIR/issue-21232-partial-init-and-use.rs:134:5
+   |
+LL |     t.0 = 10;
+   |     ^^^^^^^^ use of possibly uninitialized `t`
+
+error[E0382]: assign to part of moved value: `s`
+  --> $DIR/issue-21232-partial-init-and-use.rs:141:5
+   |
+LL |     let mut s: S<B> = S::new(); drop(s);
+   |                                      - value moved here
+LL |     s.x = 10;
+   |     ^^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `s` has type `S<std::boxed::Box<u32>>`, which does not implement the `Copy` trait
+
+error[E0382]: assign to part of moved value: `t`
+  --> $DIR/issue-21232-partial-init-and-use.rs:148:5
+   |
+LL |     let mut t: T = (0, Box::new(0)); drop(t);
+   |                                           - value moved here
+LL |     t.0 = 10;
+   |     ^^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `t` has type `(u32, std::boxed::Box<u32>)`, which does not implement the `Copy` trait
+
+error[E0381]: assign to part of possibly uninitialized variable: `s`
+  --> $DIR/issue-21232-partial-init-and-use.rs:155:5
+   |
+LL |     s.x = 10;
+   |     ^^^^^^^^ use of possibly uninitialized `s`
+
+error[E0381]: assign to part of possibly uninitialized variable: `t`
+  --> $DIR/issue-21232-partial-init-and-use.rs:162:5
+   |
+LL |     t.0 = 10;
+   |     ^^^^^^^^ use of possibly uninitialized `t`
+
+error[E0381]: assign to part of possibly uninitialized variable: `q`
+  --> $DIR/issue-21232-partial-init-and-use.rs:178:5
+   |
+LL |     q.r.f.x = 10; q.r.f.y = Box::new(20);
+   |     ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f`
+
+error[E0381]: assign to part of possibly uninitialized variable: `q`
+  --> $DIR/issue-21232-partial-init-and-use.rs:185:5
+   |
+LL |     q.r.f.0 = 10; q.r.f.1 = Box::new(20);
+   |     ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f`
+
+error[E0382]: assign to part of moved value: `q.r`
+  --> $DIR/issue-21232-partial-init-and-use.rs:192:5
+   |
+LL |     let mut q: Q<S<B>> = Q::new(S::new()); drop(q.r);
+   |                                                 --- value moved here
+LL |     q.r.f.x = 10; q.r.f.y = Box::new(20);
+   |     ^^^^^^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `q.r` has type `R<S<std::boxed::Box<u32>>>`, which does not implement the `Copy` trait
+
+error[E0382]: assign to part of moved value: `q.r`
+  --> $DIR/issue-21232-partial-init-and-use.rs:199:5
+   |
+LL |     let mut q: Q<T> = Q::new((0, Box::new(0))); drop(q.r);
+   |                                                      --- value moved here
+LL |     q.r.f.0 = 10; q.r.f.1 = Box::new(20);
+   |     ^^^^^^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `q.r` has type `R<(u32, std::boxed::Box<u32>)>`, which does not implement the `Copy` trait
+
+error[E0381]: assign to part of possibly uninitialized variable: `q`
+  --> $DIR/issue-21232-partial-init-and-use.rs:206:5
+   |
+LL |     q.r.f.x = 10;
+   |     ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f`
+
+error[E0381]: assign to part of possibly uninitialized variable: `q`
+  --> $DIR/issue-21232-partial-init-and-use.rs:213:5
+   |
+LL |     q.r.f.0 = 10;
+   |     ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f`
+
+error[E0382]: assign to part of moved value: `q.r`
+  --> $DIR/issue-21232-partial-init-and-use.rs:220:5
+   |
+LL |     let mut q: Q<S<B>> = Q::new(S::new()); drop(q.r);
+   |                                                 --- value moved here
+LL |     q.r.f.x = 10;
+   |     ^^^^^^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `q.r` has type `R<S<std::boxed::Box<u32>>>`, which does not implement the `Copy` trait
+
+error[E0382]: assign to part of moved value: `q.r`
+  --> $DIR/issue-21232-partial-init-and-use.rs:227:5
+   |
+LL |     let mut q: Q<T> = Q::new((0, Box::new(0))); drop(q.r);
+   |                                                      --- value moved here
+LL |     q.r.f.0 = 10;
+   |     ^^^^^^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `q.r` has type `R<(u32, std::boxed::Box<u32>)>`, which does not implement the `Copy` trait
+
+error[E0381]: assign to part of possibly uninitialized variable: `q`
+  --> $DIR/issue-21232-partial-init-and-use.rs:234:5
+   |
+LL |     q.r.f.x = 10;
+   |     ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f`
+
+error[E0381]: assign to part of possibly uninitialized variable: `q`
+  --> $DIR/issue-21232-partial-init-and-use.rs:241:5
+   |
+LL |     q.r.f.0 = 10;
+   |     ^^^^^^^^^^^^ use of possibly uninitialized `q.r.f`
+
+error[E0382]: assign to part of moved value: `c`
+  --> $DIR/issue-21232-partial-init-and-use.rs:259:13
+   |
+LL |         c2 => {
+   |         -- value moved here
+LL |             c.0 = 2; //~ ERROR assign to part of moved value
+   |             ^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `c` has type `(i32, std::string::String)`, which does not implement the `Copy` trait
+
+error[E0382]: assign to part of moved value: `c`
+  --> $DIR/issue-21232-partial-init-and-use.rs:269:13
+   |
+LL |         c2 => {
+   |         -- value moved here
+LL |             (c.1).0 = 2; //~ ERROR assign to part of moved value
+   |             ^^^^^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `c` has type `(i32, (i32, std::string::String))`, which does not implement the `Copy` trait
+
+error[E0382]: assign to part of moved value: `c.1`
+  --> $DIR/issue-21232-partial-init-and-use.rs:277:13
+   |
+LL |         c2 => {
+   |         -- value moved here
+LL |             ((c.1).1).0 = 3; //~ ERROR assign to part of moved value
+   |             ^^^^^^^^^^^^^^^ value partially assigned here after move
+   |
+   = note: move occurs because `c.1` has type `(i32, (i32, std::string::String))`, which does not implement the `Copy` trait
+
+error: aborting due to 23 previous errors
+
+Some errors occurred: E0381, E0382.
+For more information about an error, try `rustc --explain E0381`.