summaryrefslogtreecommitdiffstats
path: root/src/test/ui/liveness
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /src/test/ui/liveness
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/test/ui/liveness')
-rw-r--r--src/test/ui/liveness/liveness-asm.rs45
-rw-r--r--src/test/ui/liveness/liveness-asm.stderr23
-rw-r--r--src/test/ui/liveness/liveness-assign-imm-local-after-ret.rs16
-rw-r--r--src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.rs12
-rw-r--r--src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.stderr12
-rw-r--r--src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.rs12
-rw-r--r--src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.stderr14
-rw-r--r--src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs12
-rw-r--r--src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.stderr15
-rw-r--r--src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.rs12
-rw-r--r--src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.stderr15
-rw-r--r--src/test/ui/liveness/liveness-closure-require-ret.rs2
-rw-r--r--src/test/ui/liveness/liveness-closure-require-ret.stderr9
-rw-r--r--src/test/ui/liveness/liveness-consts.rs63
-rw-r--r--src/test/ui/liveness/liveness-consts.stderr63
-rw-r--r--src/test/ui/liveness/liveness-dead.rs39
-rw-r--r--src/test/ui/liveness/liveness-dead.stderr39
-rw-r--r--src/test/ui/liveness/liveness-derive.rs38
-rw-r--r--src/test/ui/liveness/liveness-derive.stderr21
-rw-r--r--src/test/ui/liveness/liveness-forgot-ret.rs6
-rw-r--r--src/test/ui/liveness/liveness-forgot-ret.stderr16
-rw-r--r--src/test/ui/liveness/liveness-issue-2163.rs8
-rw-r--r--src/test/ui/liveness/liveness-issue-2163.stderr12
-rw-r--r--src/test/ui/liveness/liveness-missing-ret2.rs7
-rw-r--r--src/test/ui/liveness/liveness-missing-ret2.stderr11
-rw-r--r--src/test/ui/liveness/liveness-move-call-arg.rs11
-rw-r--r--src/test/ui/liveness/liveness-move-call-arg.stderr12
-rw-r--r--src/test/ui/liveness/liveness-move-in-loop.rs17
-rw-r--r--src/test/ui/liveness/liveness-move-in-loop.stderr12
-rw-r--r--src/test/ui/liveness/liveness-move-in-while.rs13
-rw-r--r--src/test/ui/liveness/liveness-move-in-while.stderr36
-rw-r--r--src/test/ui/liveness/liveness-return-last-stmt-semi.rs19
-rw-r--r--src/test/ui/liveness/liveness-return-last-stmt-semi.stderr42
-rw-r--r--src/test/ui/liveness/liveness-unused.rs141
-rw-r--r--src/test/ui/liveness/liveness-unused.stderr116
-rw-r--r--src/test/ui/liveness/liveness-upvars.rs144
-rw-r--r--src/test/ui/liveness/liveness-upvars.stderr185
-rw-r--r--src/test/ui/liveness/liveness-use-after-move.rs8
-rw-r--r--src/test/ui/liveness/liveness-use-after-move.stderr16
-rw-r--r--src/test/ui/liveness/liveness-use-after-send.rs19
-rw-r--r--src/test/ui/liveness/liveness-use-after-send.stderr15
41 files changed, 1328 insertions, 0 deletions
diff --git a/src/test/ui/liveness/liveness-asm.rs b/src/test/ui/liveness/liveness-asm.rs
new file mode 100644
index 000000000..ea5f033cb
--- /dev/null
+++ b/src/test/ui/liveness/liveness-asm.rs
@@ -0,0 +1,45 @@
+// Ensure inout asm! operands are marked as used by the liveness pass
+
+// only-x86_64
+// check-pass
+
+#![allow(dead_code)]
+#![warn(unused_assignments)]
+#![warn(unused_variables)]
+
+use std::arch::asm;
+
+// Test the single inout case
+unsafe fn f1(mut src: *const u8) {
+ asm!("/*{0}*/", inout(reg) src); //~ WARN value assigned to `src` is never read
+}
+
+unsafe fn f2(mut src: *const u8) -> *const u8 {
+ asm!("/*{0}*/", inout(reg) src);
+ src
+}
+
+// Test the split inout case
+unsafe fn f3(mut src: *const u8) {
+ asm!("/*{0}*/", inout(reg) src => src); //~ WARN value assigned to `src` is never read
+}
+
+unsafe fn f4(mut src: *const u8) -> *const u8 {
+ asm!("/*{0}*/", inout(reg) src => src);
+ src
+}
+
+// Tests the use of field projections
+struct S {
+ field: *mut u8,
+}
+
+unsafe fn f5(src: &mut S) {
+ asm!("/*{0}*/", inout(reg) src.field);
+}
+
+unsafe fn f6(src: &mut S) {
+ asm!("/*{0}*/", inout(reg) src.field => src.field);
+}
+
+fn main() {}
diff --git a/src/test/ui/liveness/liveness-asm.stderr b/src/test/ui/liveness/liveness-asm.stderr
new file mode 100644
index 000000000..d052aca33
--- /dev/null
+++ b/src/test/ui/liveness/liveness-asm.stderr
@@ -0,0 +1,23 @@
+warning: value assigned to `src` is never read
+ --> $DIR/liveness-asm.rs:14:32
+ |
+LL | asm!("/*{0}*/", inout(reg) src);
+ | ^^^
+ |
+note: the lint level is defined here
+ --> $DIR/liveness-asm.rs:7:9
+ |
+LL | #![warn(unused_assignments)]
+ | ^^^^^^^^^^^^^^^^^^
+ = help: maybe it is overwritten before being read?
+
+warning: value assigned to `src` is never read
+ --> $DIR/liveness-asm.rs:24:39
+ |
+LL | asm!("/*{0}*/", inout(reg) src => src);
+ | ^^^
+ |
+ = help: maybe it is overwritten before being read?
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/liveness/liveness-assign-imm-local-after-ret.rs b/src/test/ui/liveness/liveness-assign-imm-local-after-ret.rs
new file mode 100644
index 000000000..b463f4368
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign-imm-local-after-ret.rs
@@ -0,0 +1,16 @@
+// run-pass
+
+#![allow(unreachable_code)]
+// pretty-expanded FIXME #23616
+
+#![allow(dead_code)]
+
+fn test() {
+ let _v: isize;
+ _v = 1;
+ return;
+ _v = 2;
+}
+
+pub fn main() {
+}
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.rs b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.rs
new file mode 100644
index 000000000..08911c5bd
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.rs
@@ -0,0 +1,12 @@
+fn test() {
+ let v: isize;
+ //~^ HELP consider making this binding mutable
+ //~| SUGGESTION mut v
+ loop {
+ v = 1; //~ ERROR cannot assign twice to immutable variable `v`
+ //~| NOTE cannot assign twice to immutable variable
+ }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.stderr
new file mode 100644
index 000000000..66cdce7da
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.stderr
@@ -0,0 +1,12 @@
+error[E0384]: cannot assign twice to immutable variable `v`
+ --> $DIR/liveness-assign-imm-local-in-loop.rs:6:9
+ |
+LL | let v: isize;
+ | - help: consider making this binding mutable: `mut v`
+...
+LL | v = 1;
+ | ^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.rs b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.rs
new file mode 100644
index 000000000..1752d9690
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.rs
@@ -0,0 +1,12 @@
+fn test() {
+ let v: isize;
+ //~^ HELP consider making this binding mutable
+ //~| SUGGESTION mut v
+ v = 2; //~ NOTE first assignment
+ v += 1; //~ ERROR cannot assign twice to immutable variable `v`
+ //~| NOTE cannot assign twice to immutable
+ v.clone();
+}
+
+fn main() {
+}
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.stderr
new file mode 100644
index 000000000..5db9539cb
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.stderr
@@ -0,0 +1,14 @@
+error[E0384]: cannot assign twice to immutable variable `v`
+ --> $DIR/liveness-assign-imm-local-in-op-eq.rs:6:5
+ |
+LL | let v: isize;
+ | - help: consider making this binding mutable: `mut v`
+...
+LL | v = 2;
+ | ----- first assignment to `v`
+LL | v += 1;
+ | ^^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs
new file mode 100644
index 000000000..c9b16e439
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs
@@ -0,0 +1,12 @@
+fn test() {
+ let b = Box::new(1); //~ NOTE first assignment
+ //~| HELP consider making this binding mutable
+ //~| SUGGESTION mut b
+ drop(b);
+ b = Box::new(2); //~ ERROR cannot assign twice to immutable variable `b`
+ //~| NOTE cannot assign twice to immutable
+ drop(b);
+}
+
+fn main() {
+}
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.stderr
new file mode 100644
index 000000000..bb7e7e27a
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.stderr
@@ -0,0 +1,15 @@
+error[E0384]: cannot assign twice to immutable variable `b`
+ --> $DIR/liveness-assign-imm-local-with-drop.rs:6:5
+ |
+LL | let b = Box::new(1);
+ | -
+ | |
+ | first assignment to `b`
+ | help: consider making this binding mutable: `mut b`
+...
+LL | b = Box::new(2);
+ | ^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.rs b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.rs
new file mode 100644
index 000000000..4bb2db27a
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.rs
@@ -0,0 +1,12 @@
+fn test() {
+ let v: isize = 1; //~ NOTE first assignment
+ //~| HELP consider making this binding mutable
+ //~| SUGGESTION mut v
+ v.clone();
+ v = 2; //~ ERROR cannot assign twice to immutable variable `v`
+ //~| NOTE cannot assign twice to immutable
+ v.clone();
+}
+
+fn main() {
+}
diff --git a/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.stderr b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.stderr
new file mode 100644
index 000000000..80458a70a
--- /dev/null
+++ b/src/test/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.stderr
@@ -0,0 +1,15 @@
+error[E0384]: cannot assign twice to immutable variable `v`
+ --> $DIR/liveness-assign-imm-local-with-init.rs:6:5
+ |
+LL | let v: isize = 1;
+ | -
+ | |
+ | first assignment to `v`
+ | help: consider making this binding mutable: `mut v`
+...
+LL | v = 2;
+ | ^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/liveness/liveness-closure-require-ret.rs b/src/test/ui/liveness/liveness-closure-require-ret.rs
new file mode 100644
index 000000000..b86d1fe4a
--- /dev/null
+++ b/src/test/ui/liveness/liveness-closure-require-ret.rs
@@ -0,0 +1,2 @@
+fn force<F>(f: F) -> isize where F: FnOnce() -> isize { f() }
+fn main() { println!("{}", force(|| {})); } //~ ERROR mismatched types
diff --git a/src/test/ui/liveness/liveness-closure-require-ret.stderr b/src/test/ui/liveness/liveness-closure-require-ret.stderr
new file mode 100644
index 000000000..07b2ef6cd
--- /dev/null
+++ b/src/test/ui/liveness/liveness-closure-require-ret.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+ --> $DIR/liveness-closure-require-ret.rs:2:37
+ |
+LL | fn main() { println!("{}", force(|| {})); }
+ | ^^ expected `isize`, found `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/liveness/liveness-consts.rs b/src/test/ui/liveness/liveness-consts.rs
new file mode 100644
index 000000000..8fe2453ca
--- /dev/null
+++ b/src/test/ui/liveness/liveness-consts.rs
@@ -0,0 +1,63 @@
+// check-pass
+#![warn(unused)]
+#![allow(unreachable_code)]
+
+pub static A: i32 = {
+ let mut i = 0;
+ let mut a = 0; //~ WARN variable `a` is assigned to, but never used
+ while i < 10 {
+ i += 1;
+ a += 1;
+ }
+ i
+};
+
+pub const B: u32 = {
+ let mut b = 1;
+ b += 1; //~ WARN value assigned to `b` is never read
+ b = 42;
+ b
+};
+
+pub enum E {
+ V1 = {
+ let e = 1; //~ WARN unused variable: `e`
+ 1
+ },
+ V2 = {
+ let _f = 10;
+ 2
+ }
+}
+
+pub fn f(x: [u8; { let s = 17; 100 }]) -> [u8; { let z = 18; 100 }] {
+ //~^ WARN unused variable: `s`
+ //~| WARN unused variable: `z`
+ x
+}
+
+pub trait T {
+ const T: usize = {
+ let mut t = 10;
+ t = t + t; //~ WARN value assigned to `t` is never read
+ 20
+ };
+}
+
+impl T for String {
+ const T: usize = {
+ let w = 10; //~ WARN unused variable: `w`
+ loop {
+ break;
+ let _ = w;
+ }
+ 44
+ };
+}
+
+fn main() {
+ let _ = [(); {
+ let z = 42; //~ WARN unused variable: `z`
+ 35
+ }];
+}
diff --git a/src/test/ui/liveness/liveness-consts.stderr b/src/test/ui/liveness/liveness-consts.stderr
new file mode 100644
index 000000000..adaf54316
--- /dev/null
+++ b/src/test/ui/liveness/liveness-consts.stderr
@@ -0,0 +1,63 @@
+warning: variable `a` is assigned to, but never used
+ --> $DIR/liveness-consts.rs:7:13
+ |
+LL | let mut a = 0;
+ | ^
+ |
+note: the lint level is defined here
+ --> $DIR/liveness-consts.rs:2:9
+ |
+LL | #![warn(unused)]
+ | ^^^^^^
+ = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
+ = note: consider using `_a` instead
+
+warning: value assigned to `b` is never read
+ --> $DIR/liveness-consts.rs:17:5
+ |
+LL | b += 1;
+ | ^
+ |
+ = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
+ = help: maybe it is overwritten before being read?
+
+warning: unused variable: `e`
+ --> $DIR/liveness-consts.rs:24:13
+ |
+LL | let e = 1;
+ | ^ help: if this is intentional, prefix it with an underscore: `_e`
+
+warning: unused variable: `s`
+ --> $DIR/liveness-consts.rs:33:24
+ |
+LL | pub fn f(x: [u8; { let s = 17; 100 }]) -> [u8; { let z = 18; 100 }] {
+ | ^ help: if this is intentional, prefix it with an underscore: `_s`
+
+warning: unused variable: `z`
+ --> $DIR/liveness-consts.rs:33:55
+ |
+LL | pub fn f(x: [u8; { let s = 17; 100 }]) -> [u8; { let z = 18; 100 }] {
+ | ^ help: if this is intentional, prefix it with an underscore: `_z`
+
+warning: unused variable: `z`
+ --> $DIR/liveness-consts.rs:60:13
+ |
+LL | let z = 42;
+ | ^ help: if this is intentional, prefix it with an underscore: `_z`
+
+warning: value assigned to `t` is never read
+ --> $DIR/liveness-consts.rs:42:9
+ |
+LL | t = t + t;
+ | ^
+ |
+ = help: maybe it is overwritten before being read?
+
+warning: unused variable: `w`
+ --> $DIR/liveness-consts.rs:49:13
+ |
+LL | let w = 10;
+ | ^ help: if this is intentional, prefix it with an underscore: `_w`
+
+warning: 8 warnings emitted
+
diff --git a/src/test/ui/liveness/liveness-dead.rs b/src/test/ui/liveness/liveness-dead.rs
new file mode 100644
index 000000000..004663c85
--- /dev/null
+++ b/src/test/ui/liveness/liveness-dead.rs
@@ -0,0 +1,39 @@
+#![allow(dead_code)]
+#![deny(unused_assignments)]
+
+fn f1(x: &mut isize) {
+ *x = 1; // no error
+}
+
+fn f2() {
+ let mut x: isize = 3; //~ ERROR: value assigned to `x` is never read
+ x = 4;
+ x.clone();
+}
+
+fn f3() {
+ let mut x: isize = 3;
+ x.clone();
+ x = 4; //~ ERROR: value assigned to `x` is never read
+}
+
+fn f4(mut x: i32) { //~ ERROR: value passed to `x` is never read
+ x = 4;
+ x.clone();
+}
+
+fn f5(mut x: i32) {
+ x.clone();
+ x = 4; //~ ERROR: value assigned to `x` is never read
+}
+
+// #22630
+fn f6() {
+ let mut done = false;
+ while !done {
+ done = true; // no error
+ continue;
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/liveness/liveness-dead.stderr b/src/test/ui/liveness/liveness-dead.stderr
new file mode 100644
index 000000000..12680ab11
--- /dev/null
+++ b/src/test/ui/liveness/liveness-dead.stderr
@@ -0,0 +1,39 @@
+error: value assigned to `x` is never read
+ --> $DIR/liveness-dead.rs:9:13
+ |
+LL | let mut x: isize = 3;
+ | ^
+ |
+note: the lint level is defined here
+ --> $DIR/liveness-dead.rs:2:9
+ |
+LL | #![deny(unused_assignments)]
+ | ^^^^^^^^^^^^^^^^^^
+ = help: maybe it is overwritten before being read?
+
+error: value assigned to `x` is never read
+ --> $DIR/liveness-dead.rs:17:5
+ |
+LL | x = 4;
+ | ^
+ |
+ = help: maybe it is overwritten before being read?
+
+error: value passed to `x` is never read
+ --> $DIR/liveness-dead.rs:20:11
+ |
+LL | fn f4(mut x: i32) {
+ | ^
+ |
+ = help: maybe it is overwritten before being read?
+
+error: value assigned to `x` is never read
+ --> $DIR/liveness-dead.rs:27:5
+ |
+LL | x = 4;
+ | ^
+ |
+ = help: maybe it is overwritten before being read?
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/liveness/liveness-derive.rs b/src/test/ui/liveness/liveness-derive.rs
new file mode 100644
index 000000000..1921d0d72
--- /dev/null
+++ b/src/test/ui/liveness/liveness-derive.rs
@@ -0,0 +1,38 @@
+// Test for interaction between #[automatically_derived] attribute used by
+// built-in derives and lints generated by liveness pass.
+//
+// edition:2018
+// check-pass
+#![warn(unused)]
+
+pub trait T: Sized {
+ const N: usize;
+ fn t(&self) -> Self;
+}
+
+impl T for u32 {
+ const N: usize = {
+ let a = 0; //~ WARN unused variable: `a`
+ 4
+ };
+
+ fn t(&self) -> Self {
+ let b = 16; //~ WARN unused variable: `b`
+ 0
+ }
+}
+
+#[automatically_derived]
+impl T for i32 {
+ const N: usize = {
+ let c = 0;
+ 4
+ };
+
+ fn t(&self) -> Self {
+ let d = 17;
+ 0
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/liveness/liveness-derive.stderr b/src/test/ui/liveness/liveness-derive.stderr
new file mode 100644
index 000000000..c03d90991
--- /dev/null
+++ b/src/test/ui/liveness/liveness-derive.stderr
@@ -0,0 +1,21 @@
+warning: unused variable: `a`
+ --> $DIR/liveness-derive.rs:15:13
+ |
+LL | let a = 0;
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+ |
+note: the lint level is defined here
+ --> $DIR/liveness-derive.rs:6:9
+ |
+LL | #![warn(unused)]
+ | ^^^^^^
+ = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
+
+warning: unused variable: `b`
+ --> $DIR/liveness-derive.rs:20:13
+ |
+LL | let b = 16;
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/liveness/liveness-forgot-ret.rs b/src/test/ui/liveness/liveness-forgot-ret.rs
new file mode 100644
index 000000000..b8c2bc734
--- /dev/null
+++ b/src/test/ui/liveness/liveness-forgot-ret.rs
@@ -0,0 +1,6 @@
+fn god_exists(a: isize) -> bool { return god_exists(a); }
+
+fn f(a: isize) -> isize { if god_exists(a) { return 5; }; }
+//~^ ERROR mismatched types
+
+fn main() { f(12); }
diff --git a/src/test/ui/liveness/liveness-forgot-ret.stderr b/src/test/ui/liveness/liveness-forgot-ret.stderr
new file mode 100644
index 000000000..ddbdbdb0f
--- /dev/null
+++ b/src/test/ui/liveness/liveness-forgot-ret.stderr
@@ -0,0 +1,16 @@
+error[E0308]: mismatched types
+ --> $DIR/liveness-forgot-ret.rs:3:19
+ |
+LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; }
+ | - ^^^^^ expected `isize`, found `()`
+ | |
+ | implicitly returns `()` as its body has no tail or `return` expression
+ |
+help: consider returning the local binding `a`
+ |
+LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; a }
+ | +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/liveness/liveness-issue-2163.rs b/src/test/ui/liveness/liveness-issue-2163.rs
new file mode 100644
index 000000000..a632b5b9c
--- /dev/null
+++ b/src/test/ui/liveness/liveness-issue-2163.rs
@@ -0,0 +1,8 @@
+use std::vec::Vec;
+
+fn main() {
+ let a: Vec<isize> = Vec::new();
+ a.iter().all(|_| -> bool {
+ //~^ ERROR mismatched types
+ });
+}
diff --git a/src/test/ui/liveness/liveness-issue-2163.stderr b/src/test/ui/liveness/liveness-issue-2163.stderr
new file mode 100644
index 000000000..2adc2d438
--- /dev/null
+++ b/src/test/ui/liveness/liveness-issue-2163.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+ --> $DIR/liveness-issue-2163.rs:5:30
+ |
+LL | a.iter().all(|_| -> bool {
+ | ______________________________^
+LL | |
+LL | | });
+ | |_____^ expected `bool`, found `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/liveness/liveness-missing-ret2.rs b/src/test/ui/liveness/liveness-missing-ret2.rs
new file mode 100644
index 000000000..a18669f72
--- /dev/null
+++ b/src/test/ui/liveness/liveness-missing-ret2.rs
@@ -0,0 +1,7 @@
+fn f() -> isize { //~ ERROR mismatched types
+ // Make sure typestate doesn't interpret this match expression as
+ // the function result
+ match true { true => { } _ => {} };
+}
+
+fn main() { }
diff --git a/src/test/ui/liveness/liveness-missing-ret2.stderr b/src/test/ui/liveness/liveness-missing-ret2.stderr
new file mode 100644
index 000000000..afdb733cd
--- /dev/null
+++ b/src/test/ui/liveness/liveness-missing-ret2.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+ --> $DIR/liveness-missing-ret2.rs:1:11
+ |
+LL | fn f() -> isize {
+ | - ^^^^^ expected `isize`, found `()`
+ | |
+ | implicitly returns `()` as its body has no tail or `return` expression
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/liveness/liveness-move-call-arg.rs b/src/test/ui/liveness/liveness-move-call-arg.rs
new file mode 100644
index 000000000..1bc2ea6b9
--- /dev/null
+++ b/src/test/ui/liveness/liveness-move-call-arg.rs
@@ -0,0 +1,11 @@
+fn take(_x: Box<isize>) {}
+
+
+fn main() {
+
+ let x: Box<isize> = Box::new(25);
+
+ loop {
+ take(x); //~ ERROR use of moved value: `x`
+ }
+}
diff --git a/src/test/ui/liveness/liveness-move-call-arg.stderr b/src/test/ui/liveness/liveness-move-call-arg.stderr
new file mode 100644
index 000000000..7c0e916ed
--- /dev/null
+++ b/src/test/ui/liveness/liveness-move-call-arg.stderr
@@ -0,0 +1,12 @@
+error[E0382]: use of moved value: `x`
+ --> $DIR/liveness-move-call-arg.rs:9:14
+ |
+LL | let x: Box<isize> = Box::new(25);
+ | - move occurs because `x` has type `Box<isize>`, which does not implement the `Copy` trait
+...
+LL | take(x);
+ | ^ value moved here, in previous iteration of loop
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/liveness/liveness-move-in-loop.rs b/src/test/ui/liveness/liveness-move-in-loop.rs
new file mode 100644
index 000000000..064be14d6
--- /dev/null
+++ b/src/test/ui/liveness/liveness-move-in-loop.rs
@@ -0,0 +1,17 @@
+fn main() {
+
+ let y: Box<isize> = 42.into();
+ let mut x: Box<isize>;
+
+ loop {
+ println!("{}", y);
+ loop {
+ loop {
+ loop {
+ x = y; //~ ERROR use of moved value
+ x.clone();
+ }
+ }
+ }
+ }
+}
diff --git a/src/test/ui/liveness/liveness-move-in-loop.stderr b/src/test/ui/liveness/liveness-move-in-loop.stderr
new file mode 100644
index 000000000..832d4f8fa
--- /dev/null
+++ b/src/test/ui/liveness/liveness-move-in-loop.stderr
@@ -0,0 +1,12 @@
+error[E0382]: use of moved value: `y`
+ --> $DIR/liveness-move-in-loop.rs:11:25
+ |
+LL | let y: Box<isize> = 42.into();
+ | - move occurs because `y` has type `Box<isize>`, which does not implement the `Copy` trait
+...
+LL | x = y;
+ | ^ value moved here, in previous iteration of loop
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/liveness/liveness-move-in-while.rs b/src/test/ui/liveness/liveness-move-in-while.rs
new file mode 100644
index 000000000..7c0cd282c
--- /dev/null
+++ b/src/test/ui/liveness/liveness-move-in-while.rs
@@ -0,0 +1,13 @@
+fn main() {
+
+ let y: Box<isize> = 42.into();
+ let mut x: Box<isize>;
+
+ loop {
+ println!("{}", y); //~ ERROR borrow of moved value: `y`
+ while true { while true { while true { x = y; x.clone(); } } }
+ //~^ WARN denote infinite loops with
+ //~| WARN denote infinite loops with
+ //~| WARN denote infinite loops with
+ }
+}
diff --git a/src/test/ui/liveness/liveness-move-in-while.stderr b/src/test/ui/liveness/liveness-move-in-while.stderr
new file mode 100644
index 000000000..b04a05fe4
--- /dev/null
+++ b/src/test/ui/liveness/liveness-move-in-while.stderr
@@ -0,0 +1,36 @@
+warning: denote infinite loops with `loop { ... }`
+ --> $DIR/liveness-move-in-while.rs:8:9
+ |
+LL | while true { while true { while true { x = y; x.clone(); } } }
+ | ^^^^^^^^^^ help: use `loop`
+ |
+ = note: `#[warn(while_true)]` on by default
+
+warning: denote infinite loops with `loop { ... }`
+ --> $DIR/liveness-move-in-while.rs:8:22
+ |
+LL | while true { while true { while true { x = y; x.clone(); } } }
+ | ^^^^^^^^^^ help: use `loop`
+
+warning: denote infinite loops with `loop { ... }`
+ --> $DIR/liveness-move-in-while.rs:8:35
+ |
+LL | while true { while true { while true { x = y; x.clone(); } } }
+ | ^^^^^^^^^^ help: use `loop`
+
+error[E0382]: borrow of moved value: `y`
+ --> $DIR/liveness-move-in-while.rs:7:24
+ |
+LL | let y: Box<isize> = 42.into();
+ | - move occurs because `y` has type `Box<isize>`, which does not implement the `Copy` trait
+...
+LL | println!("{}", y);
+ | ^ value borrowed here after move
+LL | while true { while true { while true { x = y; x.clone(); } } }
+ | - value moved here, in previous iteration of loop
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error; 3 warnings emitted
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/liveness/liveness-return-last-stmt-semi.rs b/src/test/ui/liveness/liveness-return-last-stmt-semi.rs
new file mode 100644
index 000000000..e8909c4a5
--- /dev/null
+++ b/src/test/ui/liveness/liveness-return-last-stmt-semi.rs
@@ -0,0 +1,19 @@
+//
+// regression test for #8005
+
+macro_rules! test { () => { fn foo() -> i32 { 1; } } }
+ //~^ ERROR mismatched types
+
+fn no_return() -> i32 {} //~ ERROR mismatched types
+
+fn bar(x: u32) -> u32 { //~ ERROR mismatched types
+ x * 2;
+}
+
+fn baz(x: u64) -> u32 { //~ ERROR mismatched types
+ x * 2;
+}
+
+fn main() {
+ test!();
+}
diff --git a/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr b/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr
new file mode 100644
index 000000000..82d136bd3
--- /dev/null
+++ b/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr
@@ -0,0 +1,42 @@
+error[E0308]: mismatched types
+ --> $DIR/liveness-return-last-stmt-semi.rs:7:19
+ |
+LL | fn no_return() -> i32 {}
+ | --------- ^^^ expected `i32`, found `()`
+ | |
+ | implicitly returns `()` as its body has no tail or `return` expression
+
+error[E0308]: mismatched types
+ --> $DIR/liveness-return-last-stmt-semi.rs:9:19
+ |
+LL | fn bar(x: u32) -> u32 {
+ | --- ^^^ expected `u32`, found `()`
+ | |
+ | implicitly returns `()` as its body has no tail or `return` expression
+LL | x * 2;
+ | - help: remove this semicolon
+
+error[E0308]: mismatched types
+ --> $DIR/liveness-return-last-stmt-semi.rs:13:19
+ |
+LL | fn baz(x: u64) -> u32 {
+ | --- ^^^ expected `u32`, found `()`
+ | |
+ | implicitly returns `()` as its body has no tail or `return` expression
+
+error[E0308]: mismatched types
+ --> $DIR/liveness-return-last-stmt-semi.rs:4:41
+ |
+LL | macro_rules! test { () => { fn foo() -> i32 { 1; } } }
+ | --- ^^^ expected `i32`, found `()`
+ | |
+ | implicitly returns `()` as its body has no tail or `return` expression
+...
+LL | test!();
+ | ------- in this macro invocation
+ |
+ = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/liveness/liveness-unused.rs b/src/test/ui/liveness/liveness-unused.rs
new file mode 100644
index 000000000..9c7be15fc
--- /dev/null
+++ b/src/test/ui/liveness/liveness-unused.rs
@@ -0,0 +1,141 @@
+#![warn(unused)]
+#![deny(unused_variables)]
+#![deny(unused_assignments)]
+#![allow(dead_code, non_camel_case_types, trivial_numeric_casts)]
+
+use std::ops::AddAssign;
+
+fn f1(x: isize) {
+ //~^ ERROR unused variable: `x`
+}
+
+fn f1b(x: &mut isize) {
+ //~^ ERROR unused variable: `x`
+}
+
+#[allow(unused_variables)]
+fn f1c(x: isize) {}
+
+fn f1d() {
+ let x: isize;
+ //~^ ERROR unused variable: `x`
+}
+
+fn f2() {
+ let x = 3;
+ //~^ ERROR unused variable: `x`
+}
+
+fn f3() {
+ let mut x = 3;
+ //~^ ERROR variable `x` is assigned to, but never used
+ x += 4;
+ //~^ ERROR value assigned to `x` is never read
+}
+
+fn f3b() {
+ let mut z = 3;
+ //~^ ERROR variable `z` is assigned to, but never used
+ loop {
+ z += 4;
+ }
+}
+
+#[allow(unused_variables)]
+fn f3c() {
+ let mut z = 3;
+ loop { z += 4; }
+}
+
+#[allow(unused_variables)]
+#[allow(unused_assignments)]
+fn f3d() {
+ let mut x = 3;
+ x += 4;
+}
+
+fn f4() {
+ match Some(3) {
+ Some(i) => {
+ //~^ ERROR unused variable: `i`
+ }
+ None => {}
+ }
+}
+
+enum tri {
+ a(isize), b(isize), c(isize)
+}
+
+fn f4b() -> isize {
+ match tri::a(3) {
+ tri::a(i) | tri::b(i) | tri::c(i) => {
+ i
+ }
+ }
+}
+
+fn f5a() {
+ for x in 1..10 { }
+ //~^ ERROR unused variable: `x`
+}
+
+fn f5b() {
+ for (x, _) in [1, 2, 3].iter().enumerate() { }
+ //~^ ERROR unused variable: `x`
+}
+
+fn f5c() {
+ for (_, x) in [1, 2, 3].iter().enumerate() {
+ //~^ ERROR unused variable: `x`
+ continue;
+ drop(*x as i32); //~ WARNING unreachable statement
+ }
+}
+
+struct View<'a>(&'a mut [i32]);
+
+impl<'a> AddAssign<i32> for View<'a> {
+ fn add_assign(&mut self, rhs: i32) {
+ for lhs in self.0.iter_mut() {
+ *lhs += rhs;
+ }
+ }
+}
+
+fn f6() {
+ let mut array = [1, 2, 3];
+ let mut v = View(&mut array);
+
+ // ensure an error shows up for x even if lhs of an overloaded add assign
+
+ let x;
+ //~^ ERROR variable `x` is assigned to, but never used
+
+ *({
+ x = 0; //~ ERROR value assigned to `x` is never read
+ &mut v
+ }) += 1;
+}
+
+
+struct MutRef<'a>(&'a mut i32);
+
+impl<'a> AddAssign<i32> for MutRef<'a> {
+ fn add_assign(&mut self, rhs: i32) {
+ *self.0 += rhs;
+ }
+}
+
+fn f7() {
+ let mut a = 1;
+ {
+ // `b` does not trigger unused_variables
+ let mut b = MutRef(&mut a);
+ b += 1;
+ }
+ drop(a);
+}
+
+fn main() {
+}
diff --git a/src/test/ui/liveness/liveness-unused.stderr b/src/test/ui/liveness/liveness-unused.stderr
new file mode 100644
index 000000000..4a6122681
--- /dev/null
+++ b/src/test/ui/liveness/liveness-unused.stderr
@@ -0,0 +1,116 @@
+warning: unreachable statement
+ --> $DIR/liveness-unused.rs:92:9
+ |
+LL | continue;
+ | -------- any code following this expression is unreachable
+LL | drop(*x as i32);
+ | ^^^^^^^^^^^^^^^^ unreachable statement
+ |
+note: the lint level is defined here
+ --> $DIR/liveness-unused.rs:1:9
+ |
+LL | #![warn(unused)]
+ | ^^^^^^
+ = note: `#[warn(unreachable_code)]` implied by `#[warn(unused)]`
+
+error: unused variable: `x`
+ --> $DIR/liveness-unused.rs:8:7
+ |
+LL | fn f1(x: isize) {
+ | ^ help: if this is intentional, prefix it with an underscore: `_x`
+ |
+note: the lint level is defined here
+ --> $DIR/liveness-unused.rs:2:9
+ |
+LL | #![deny(unused_variables)]
+ | ^^^^^^^^^^^^^^^^
+
+error: unused variable: `x`
+ --> $DIR/liveness-unused.rs:12:8
+ |
+LL | fn f1b(x: &mut isize) {
+ | ^ help: if this is intentional, prefix it with an underscore: `_x`
+
+error: unused variable: `x`
+ --> $DIR/liveness-unused.rs:20:9
+ |
+LL | let x: isize;
+ | ^ help: if this is intentional, prefix it with an underscore: `_x`
+
+error: unused variable: `x`
+ --> $DIR/liveness-unused.rs:25:9
+ |
+LL | let x = 3;
+ | ^ help: if this is intentional, prefix it with an underscore: `_x`
+
+error: variable `x` is assigned to, but never used
+ --> $DIR/liveness-unused.rs:30:13
+ |
+LL | let mut x = 3;
+ | ^
+ |
+ = note: consider using `_x` instead
+
+error: value assigned to `x` is never read
+ --> $DIR/liveness-unused.rs:32:5
+ |
+LL | x += 4;
+ | ^
+ |
+note: the lint level is defined here
+ --> $DIR/liveness-unused.rs:3:9
+ |
+LL | #![deny(unused_assignments)]
+ | ^^^^^^^^^^^^^^^^^^
+ = help: maybe it is overwritten before being read?
+
+error: variable `z` is assigned to, but never used
+ --> $DIR/liveness-unused.rs:37:13
+ |
+LL | let mut z = 3;
+ | ^
+ |
+ = note: consider using `_z` instead
+
+error: unused variable: `i`
+ --> $DIR/liveness-unused.rs:59:12
+ |
+LL | Some(i) => {
+ | ^ help: if this is intentional, prefix it with an underscore: `_i`
+
+error: unused variable: `x`
+ --> $DIR/liveness-unused.rs:79:9
+ |
+LL | for x in 1..10 { }
+ | ^ help: if this is intentional, prefix it with an underscore: `_x`
+
+error: unused variable: `x`
+ --> $DIR/liveness-unused.rs:84:10
+ |
+LL | for (x, _) in [1, 2, 3].iter().enumerate() { }
+ | ^ help: if this is intentional, prefix it with an underscore: `_x`
+
+error: unused variable: `x`
+ --> $DIR/liveness-unused.rs:89:13
+ |
+LL | for (_, x) in [1, 2, 3].iter().enumerate() {
+ | ^ help: if this is intentional, prefix it with an underscore: `_x`
+
+error: variable `x` is assigned to, but never used
+ --> $DIR/liveness-unused.rs:112:9
+ |
+LL | let x;
+ | ^
+ |
+ = note: consider using `_x` instead
+
+error: value assigned to `x` is never read
+ --> $DIR/liveness-unused.rs:116:9
+ |
+LL | x = 0;
+ | ^
+ |
+ = help: maybe it is overwritten before being read?
+
+error: aborting due to 13 previous errors; 1 warning emitted
+
diff --git a/src/test/ui/liveness/liveness-upvars.rs b/src/test/ui/liveness/liveness-upvars.rs
new file mode 100644
index 000000000..d446d57d3
--- /dev/null
+++ b/src/test/ui/liveness/liveness-upvars.rs
@@ -0,0 +1,144 @@
+// edition:2018
+// check-pass
+#![feature(generators)]
+#![warn(unused)]
+#![allow(unreachable_code)]
+
+pub fn unintentional_copy_one() {
+ let mut last = None;
+ let mut f = move |s| {
+ last = Some(s); //~ WARN value assigned to `last` is never read
+ //~| WARN unused variable: `last`
+ };
+ f("a");
+ f("b");
+ f("c");
+ dbg!(last.unwrap());
+}
+
+pub fn unintentional_copy_two() {
+ let mut sum = 0;
+ (1..10).for_each(move |x| {
+ sum += x; //~ WARN unused variable: `sum`
+ });
+ dbg!(sum);
+}
+
+pub fn f() {
+ let mut c = 0;
+
+ // Captured by value, but variable is dead on entry.
+ let _ = move || {
+ c = 1; //~ WARN value captured by `c` is never read
+ println!("{}", c);
+ };
+ let _ = async move {
+ c = 1; //~ WARN value captured by `c` is never read
+ println!("{}", c);
+ };
+
+ // Read and written to, but never actually used.
+ let _ = move || {
+ c += 1; //~ WARN unused variable: `c`
+ };
+ let _ = async move {
+ c += 1; //~ WARN value assigned to `c` is never read
+ //~| WARN unused variable: `c`
+ };
+
+ let _ = move || {
+ println!("{}", c);
+ // Value is read by closure itself on later invocations.
+ c += 1;
+ };
+ let b = Box::new(42);
+ let _ = move || {
+ println!("{}", c);
+ // Never read because this is FnOnce closure.
+ c += 1; //~ WARN value assigned to `c` is never read
+ drop(b);
+ };
+ let _ = async move {
+ println!("{}", c);
+ // Never read because this is a generator.
+ c += 1; //~ WARN value assigned to `c` is never read
+ };
+}
+
+pub fn nested() {
+ let mut d = None;
+ let mut e = None;
+ let _ = || {
+ let _ = || {
+ d = Some("d1"); //~ WARN value assigned to `d` is never read
+ d = Some("d2");
+ };
+ let _ = move || {
+ e = Some("e1"); //~ WARN value assigned to `e` is never read
+ //~| WARN unused variable: `e`
+ e = Some("e2"); //~ WARN value assigned to `e` is never read
+ };
+ };
+}
+
+pub fn g<T: Default>(mut v: T) {
+ let _ = |r| {
+ if r {
+ v = T::default(); //~ WARN value assigned to `v` is never read
+ } else {
+ drop(v);
+ }
+ };
+}
+
+pub fn h<T: Copy + Default + std::fmt::Debug>() {
+ let mut z = T::default();
+ let _ = move |b| {
+ loop {
+ if b {
+ z = T::default(); //~ WARN value assigned to `z` is never read
+ //~| WARN unused variable: `z`
+ } else {
+ return;
+ }
+ }
+ dbg!(z);
+ };
+}
+
+async fn yield_now() {
+ todo!();
+}
+
+pub fn async_generator() {
+ let mut state: u32 = 0;
+
+ let _ = async {
+ state = 1;
+ yield_now().await;
+ state = 2;
+ yield_now().await;
+ state = 3;
+ };
+
+ let _ = async move {
+ state = 4; //~ WARN value assigned to `state` is never read
+ //~| WARN unused variable: `state`
+ yield_now().await;
+ state = 5; //~ WARN value assigned to `state` is never read
+ };
+}
+
+pub fn generator() {
+ let mut s: u32 = 0;
+ let _ = |_| {
+ s = 0;
+ yield ();
+ s = 1; //~ WARN value assigned to `s` is never read
+ yield (s = 2);
+ s = yield (); //~ WARN value assigned to `s` is never read
+ s = 3;
+ };
+}
+
+fn main() {}
diff --git a/src/test/ui/liveness/liveness-upvars.stderr b/src/test/ui/liveness/liveness-upvars.stderr
new file mode 100644
index 000000000..cb104e0a3
--- /dev/null
+++ b/src/test/ui/liveness/liveness-upvars.stderr
@@ -0,0 +1,185 @@
+warning: value assigned to `last` is never read
+ --> $DIR/liveness-upvars.rs:10:9
+ |
+LL | last = Some(s);
+ | ^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/liveness-upvars.rs:4:9
+ |
+LL | #![warn(unused)]
+ | ^^^^^^
+ = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
+ = help: maybe it is overwritten before being read?
+
+warning: unused variable: `last`
+ --> $DIR/liveness-upvars.rs:10:9
+ |
+LL | last = Some(s);
+ | ^^^^
+ |
+ = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
+ = help: did you mean to capture by reference instead?
+
+warning: unused variable: `sum`
+ --> $DIR/liveness-upvars.rs:22:9
+ |
+LL | sum += x;
+ | ^^^
+ |
+ = help: did you mean to capture by reference instead?
+
+warning: value captured by `c` is never read
+ --> $DIR/liveness-upvars.rs:32:9
+ |
+LL | c = 1;
+ | ^
+ |
+ = help: did you mean to capture by reference instead?
+
+warning: value captured by `c` is never read
+ --> $DIR/liveness-upvars.rs:36:9
+ |
+LL | c = 1;
+ | ^
+ |
+ = help: did you mean to capture by reference instead?
+
+warning: unused variable: `c`
+ --> $DIR/liveness-upvars.rs:42:9
+ |
+LL | c += 1;
+ | ^
+ |
+ = help: did you mean to capture by reference instead?
+
+warning: value assigned to `c` is never read
+ --> $DIR/liveness-upvars.rs:45:9
+ |
+LL | c += 1;
+ | ^
+ |
+ = help: maybe it is overwritten before being read?
+
+warning: unused variable: `c`
+ --> $DIR/liveness-upvars.rs:45:9
+ |
+LL | c += 1;
+ | ^
+ |
+ = help: did you mean to capture by reference instead?
+
+warning: value assigned to `c` is never read
+ --> $DIR/liveness-upvars.rs:58:9
+ |
+LL | c += 1;
+ | ^
+ |
+ = help: maybe it is overwritten before being read?
+
+warning: value assigned to `c` is never read
+ --> $DIR/liveness-upvars.rs:64:9
+ |
+LL | c += 1;
+ | ^
+ |
+ = help: maybe it is overwritten before being read?
+
+warning: value assigned to `d` is never read
+ --> $DIR/liveness-upvars.rs:73:13
+ |
+LL | d = Some("d1");
+ | ^
+ |
+ = help: maybe it is overwritten before being read?
+
+warning: value assigned to `e` is never read
+ --> $DIR/liveness-upvars.rs:77:13
+ |
+LL | e = Some("e1");
+ | ^
+ |
+ = help: maybe it is overwritten before being read?
+
+warning: value assigned to `e` is never read
+ --> $DIR/liveness-upvars.rs:79:13
+ |
+LL | e = Some("e2");
+ | ^
+ |
+ = help: maybe it is overwritten before being read?
+
+warning: unused variable: `e`
+ --> $DIR/liveness-upvars.rs:77:13
+ |
+LL | e = Some("e1");
+ | ^
+ |
+ = help: did you mean to capture by reference instead?
+
+warning: value assigned to `v` is never read
+ --> $DIR/liveness-upvars.rs:87:13
+ |
+LL | v = T::default();
+ | ^
+ |
+ = help: maybe it is overwritten before being read?
+
+warning: value assigned to `z` is never read
+ --> $DIR/liveness-upvars.rs:99:17
+ |
+LL | z = T::default();
+ | ^
+ |
+ = help: maybe it is overwritten before being read?
+
+warning: unused variable: `z`
+ --> $DIR/liveness-upvars.rs:99:17
+ |
+LL | z = T::default();
+ | ^
+ |
+ = help: did you mean to capture by reference instead?
+
+warning: value assigned to `state` is never read
+ --> $DIR/liveness-upvars.rs:125:9
+ |
+LL | state = 4;
+ | ^^^^^
+ |
+ = help: maybe it is overwritten before being read?
+
+warning: value assigned to `state` is never read
+ --> $DIR/liveness-upvars.rs:128:9
+ |
+LL | state = 5;
+ | ^^^^^
+ |
+ = help: maybe it is overwritten before being read?
+
+warning: unused variable: `state`
+ --> $DIR/liveness-upvars.rs:125:9
+ |
+LL | state = 4;
+ | ^^^^^
+ |
+ = help: did you mean to capture by reference instead?
+
+warning: value assigned to `s` is never read
+ --> $DIR/liveness-upvars.rs:137:9
+ |
+LL | s = 1;
+ | ^
+ |
+ = help: maybe it is overwritten before being read?
+
+warning: value assigned to `s` is never read
+ --> $DIR/liveness-upvars.rs:139:9
+ |
+LL | s = yield ();
+ | ^
+ |
+ = help: maybe it is overwritten before being read?
+
+warning: 22 warnings emitted
+
diff --git a/src/test/ui/liveness/liveness-use-after-move.rs b/src/test/ui/liveness/liveness-use-after-move.rs
new file mode 100644
index 000000000..46102ca1e
--- /dev/null
+++ b/src/test/ui/liveness/liveness-use-after-move.rs
@@ -0,0 +1,8 @@
+fn main() {
+
+ let x: Box<_> = 5.into();
+ let y = x;
+
+ println!("{}", *x); //~ ERROR borrow of moved value: `x`
+ y.clone();
+}
diff --git a/src/test/ui/liveness/liveness-use-after-move.stderr b/src/test/ui/liveness/liveness-use-after-move.stderr
new file mode 100644
index 000000000..218b93c8e
--- /dev/null
+++ b/src/test/ui/liveness/liveness-use-after-move.stderr
@@ -0,0 +1,16 @@
+error[E0382]: borrow of moved value: `x`
+ --> $DIR/liveness-use-after-move.rs:6:20
+ |
+LL | let x: Box<_> = 5.into();
+ | - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+LL | let y = x;
+ | - value moved here
+LL |
+LL | println!("{}", *x);
+ | ^^ value borrowed here after move
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/liveness/liveness-use-after-send.rs b/src/test/ui/liveness/liveness-use-after-send.rs
new file mode 100644
index 000000000..6fcd91a9d
--- /dev/null
+++ b/src/test/ui/liveness/liveness-use-after-send.rs
@@ -0,0 +1,19 @@
+use std::marker;
+
+fn send<T:Send + std::fmt::Debug>(ch: Chan<T>, data: T) {
+ println!("{:?}", ch);
+ println!("{:?}", data);
+ panic!();
+}
+
+#[derive(Debug)]
+struct Chan<T>(isize, marker::PhantomData<T>);
+
+// Tests that "log(debug, message);" is flagged as using
+// message after the send deinitializes it
+fn test00_start(ch: Chan<Box<isize>>, message: Box<isize>, _count: Box<isize>) {
+ send(ch, message);
+ println!("{}", message); //~ ERROR borrow of moved value: `message`
+}
+
+fn main() { panic!(); }
diff --git a/src/test/ui/liveness/liveness-use-after-send.stderr b/src/test/ui/liveness/liveness-use-after-send.stderr
new file mode 100644
index 000000000..8edc0463f
--- /dev/null
+++ b/src/test/ui/liveness/liveness-use-after-send.stderr
@@ -0,0 +1,15 @@
+error[E0382]: borrow of moved value: `message`
+ --> $DIR/liveness-use-after-send.rs:16:20
+ |
+LL | fn test00_start(ch: Chan<Box<isize>>, message: Box<isize>, _count: Box<isize>) {
+ | ------- move occurs because `message` has type `Box<isize>`, which does not implement the `Copy` trait
+LL | send(ch, message);
+ | ------- value moved here
+LL | println!("{}", message);
+ | ^^^^^^^ value borrowed here after move
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.