From 64d98f8ee037282c35007b64c2649055c56af1db Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:19:03 +0200 Subject: Merging upstream version 1.68.2+dfsg1. Signed-off-by: Daniel Baumann --- .../2229_closure_analysis/diagnostics/arrays.rs | 85 +++++++++++++++++ .../diagnostics/arrays.stderr | 104 +++++++++++++++++++++ .../diagnostics/borrowck/borrowck-1.rs | 19 ++++ .../diagnostics/borrowck/borrowck-1.stderr | 19 ++++ .../diagnostics/borrowck/borrowck-2.rs | 19 ++++ .../diagnostics/borrowck/borrowck-2.stderr | 19 ++++ .../diagnostics/borrowck/borrowck-3.rs | 17 ++++ .../diagnostics/borrowck/borrowck-3.stderr | 22 +++++ .../diagnostics/borrowck/borrowck-4.rs | 20 ++++ .../diagnostics/borrowck/borrowck-4.stderr | 22 +++++ .../borrowck/borrowck-closures-mut-and-imm.rs | 26 ++++++ .../borrowck/borrowck-closures-mut-and-imm.stderr | 21 +++++ .../2229_closure_analysis/diagnostics/box.rs | 64 +++++++++++++ .../2229_closure_analysis/diagnostics/box.stderr | 48 ++++++++++ .../diagnostics/cant-mutate-imm-borrow.rs | 19 ++++ .../diagnostics/cant-mutate-imm-borrow.stderr | 12 +++ .../diagnostics/cant-mutate-imm.rs | 34 +++++++ .../diagnostics/cant-mutate-imm.stderr | 21 +++++ .../closure-origin-array-diagnostics.rs | 13 +++ .../closure-origin-array-diagnostics.stderr | 22 +++++ .../closure-origin-multi-variant-diagnostics.rs | 27 ++++++ ...closure-origin-multi-variant-diagnostics.stderr | 21 +++++ .../closure-origin-single-variant-diagnostics.rs | 18 ++++ ...losure-origin-single-variant-diagnostics.stderr | 21 +++++ .../closure-origin-struct-diagnostics.rs | 22 +++++ .../closure-origin-struct-diagnostics.stderr | 21 +++++ .../closure-origin-tuple-diagnostics-1.rs | 13 +++ .../closure-origin-tuple-diagnostics-1.stderr | 21 +++++ .../closure-origin-tuple-diagnostics.rs | 13 +++ .../closure-origin-tuple-diagnostics.stderr | 22 +++++ .../2229_closure_analysis/diagnostics/liveness.rs | 92 ++++++++++++++++++ .../diagnostics/liveness.stderr | 65 +++++++++++++ .../diagnostics/liveness_unintentional_copy.rs | 43 +++++++++ .../diagnostics/liveness_unintentional_copy.stderr | 33 +++++++ .../diagnostics/multilevel-path.rs | 28 ++++++ .../diagnostics/multilevel-path.stderr | 17 ++++ .../2229_closure_analysis/diagnostics/mut_ref.rs | 37 ++++++++ .../diagnostics/mut_ref.stderr | 26 ++++++ .../diagnostics/repr_packed.rs | 32 +++++++ .../diagnostics/repr_packed.stderr | 29 ++++++ .../diagnostics/simple-struct-min-capture.rs | 25 +++++ .../diagnostics/simple-struct-min-capture.stderr | 21 +++++ .../2229_closure_analysis/diagnostics/union.rs | 25 +++++ .../2229_closure_analysis/diagnostics/union.stderr | 18 ++++ 44 files changed, 1316 insertions(+) create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/arrays.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/box.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/box.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/liveness.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/mut_ref.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/union.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/union.stderr (limited to 'tests/ui/closures/2229_closure_analysis/diagnostics') diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.rs new file mode 100644 index 000000000..f97e60daf --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.rs @@ -0,0 +1,85 @@ +// edition:2021 + +// Test that arrays are completely captured by closures by relying on the borrow check diagnostics + +fn arrays_1() { + let mut arr = [1, 2, 3, 4, 5]; + + let mut c = || { + arr[0] += 10; + }; + + // c will capture `arr` completely, therefore another index into the + // array can't be modified here + arr[1] += 10; + //~^ ERROR: cannot use `arr` because it was mutably borrowed + //~| ERROR: cannot use `arr[_]` because it was mutably borrowed + c(); +} + +fn arrays_2() { + let mut arr = [1, 2, 3, 4, 5]; + + let c = || { + println!("{:#?}", &arr[3..4]); + }; + + // c will capture `arr` completely, therefore another index into the + // array can't be modified here + arr[1] += 10; + //~^ ERROR: cannot assign to `arr[_]` because it is borrowed + c(); +} + +fn arrays_3() { + let mut arr = [1, 2, 3, 4, 5]; + + let c = || { + println!("{}", arr[3]); + }; + + // c will capture `arr` completely, therefore another index into the + // array can't be modified here + arr[1] += 10; + //~^ ERROR: cannot assign to `arr[_]` because it is borrowed + c(); +} + +fn arrays_4() { + let mut arr = [1, 2, 3, 4, 5]; + + let mut c = || { + arr[1] += 10; + }; + + // c will capture `arr` completely, therefore we cannot borrow another index + // into the array. + println!("{}", arr[3]); + //~^ ERROR: cannot use `arr` because it was mutably borrowed + //~| ERROR: cannot borrow `arr[_]` as immutable because it is also borrowed as mutable + + c(); +} + +fn arrays_5() { + let mut arr = [1, 2, 3, 4, 5]; + + let mut c = || { + arr[1] += 10; + }; + + // c will capture `arr` completely, therefore we cannot borrow other indices + // into the array. + println!("{:#?}", &arr[3..2]); + //~^ ERROR: cannot borrow `arr` as immutable because it is also borrowed as mutable + + c(); +} + +fn main() { + arrays_1(); + arrays_2(); + arrays_3(); + arrays_4(); + arrays_5(); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr new file mode 100644 index 000000000..4f41060dc --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr @@ -0,0 +1,104 @@ +error[E0503]: cannot use `arr` because it was mutably borrowed + --> $DIR/arrays.rs:14:5 + | +LL | let mut c = || { + | -- borrow of `arr` occurs here +LL | arr[0] += 10; + | --- borrow occurs due to use of `arr` in closure +... +LL | arr[1] += 10; + | ^^^^^^ use of borrowed `arr` +... +LL | c(); + | - borrow later used here + +error[E0503]: cannot use `arr[_]` because it was mutably borrowed + --> $DIR/arrays.rs:14:5 + | +LL | let mut c = || { + | -- borrow of `arr` occurs here +LL | arr[0] += 10; + | --- borrow occurs due to use of `arr` in closure +... +LL | arr[1] += 10; + | ^^^^^^^^^^^^ use of borrowed `arr` +... +LL | c(); + | - borrow later used here + +error[E0506]: cannot assign to `arr[_]` because it is borrowed + --> $DIR/arrays.rs:29:5 + | +LL | let c = || { + | -- borrow of `arr[_]` occurs here +LL | println!("{:#?}", &arr[3..4]); + | --- borrow occurs due to use in closure +... +LL | arr[1] += 10; + | ^^^^^^^^^^^^ assignment to borrowed `arr[_]` occurs here +LL | +LL | c(); + | - borrow later used here + +error[E0506]: cannot assign to `arr[_]` because it is borrowed + --> $DIR/arrays.rs:43:5 + | +LL | let c = || { + | -- borrow of `arr[_]` occurs here +LL | println!("{}", arr[3]); + | --- borrow occurs due to use in closure +... +LL | arr[1] += 10; + | ^^^^^^^^^^^^ assignment to borrowed `arr[_]` occurs here +LL | +LL | c(); + | - borrow later used here + +error[E0503]: cannot use `arr` because it was mutably borrowed + --> $DIR/arrays.rs:57:20 + | +LL | let mut c = || { + | -- borrow of `arr` occurs here +LL | arr[1] += 10; + | --- borrow occurs due to use of `arr` in closure +... +LL | println!("{}", arr[3]); + | ^^^^^^ use of borrowed `arr` +... +LL | c(); + | - borrow later used here + +error[E0502]: cannot borrow `arr[_]` as immutable because it is also borrowed as mutable + --> $DIR/arrays.rs:57:20 + | +LL | let mut c = || { + | -- mutable borrow occurs here +LL | arr[1] += 10; + | --- first borrow occurs due to use of `arr` in closure +... +LL | println!("{}", arr[3]); + | ^^^^^^ immutable borrow occurs here +... +LL | c(); + | - mutable borrow later used here + | + = 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[E0502]: cannot borrow `arr` as immutable because it is also borrowed as mutable + --> $DIR/arrays.rs:73:24 + | +LL | let mut c = || { + | -- mutable borrow occurs here +LL | arr[1] += 10; + | --- first borrow occurs due to use of `arr` in closure +... +LL | println!("{:#?}", &arr[3..2]); + | ^^^ immutable borrow occurs here +... +LL | c(); + | - mutable borrow later used here + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0502, E0503, E0506. +For more information about an error, try `rustc --explain E0502`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.rs new file mode 100644 index 000000000..3664d76c2 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.rs @@ -0,0 +1,19 @@ +// edition:2021 + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} +fn main() { + let mut p = Point {x: 1, y: 2 }; + + let y = &mut p.y; + let mut c = || { + //~^ ERROR cannot borrow `p` as mutable more than once at a time + let x = &mut p.x; + println!("{:?}", p); + }; + c(); + *y+=1; +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr new file mode 100644 index 000000000..341d2bc65 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr @@ -0,0 +1,19 @@ +error[E0499]: cannot borrow `p` as mutable more than once at a time + --> $DIR/borrowck-1.rs:12:17 + | +LL | let y = &mut p.y; + | -------- first mutable borrow occurs here +LL | let mut c = || { + | ^^ second mutable borrow occurs here +LL | +LL | let x = &mut p.x; + | --- capture is mutable because of use here +LL | println!("{:?}", p); + | - second borrow occurs due to use of `p` in closure +... +LL | *y+=1; + | ----- first borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.rs new file mode 100644 index 000000000..ae416bab6 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.rs @@ -0,0 +1,19 @@ +// edition:2021 + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} +fn main() { + let mut p = Point {x: 1, y: 2 }; + + let y = &p.y; + let mut c = || { + //~^ ERROR cannot borrow `p` as mutable because it is also borrowed as immutable + println!("{:?}", p); + let x = &mut p.x; + }; + c(); + println!("{}", y); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr new file mode 100644 index 000000000..584bb862b --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr @@ -0,0 +1,19 @@ +error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-2.rs:12:17 + | +LL | let y = &p.y; + | ---- immutable borrow occurs here +LL | let mut c = || { + | ^^ mutable borrow occurs here +LL | +LL | println!("{:?}", p); + | - second borrow occurs due to use of `p` in closure +LL | let x = &mut p.x; + | --- capture is mutable because of use here +... +LL | println!("{}", y); + | - immutable borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs new file mode 100644 index 000000000..00f50c33e --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs @@ -0,0 +1,17 @@ +// edition:2021 + +#[derive(Debug)] +struct Point { + x: String, + y: String, +} +fn main() { + let mut c = { + let mut p = Point {x: "1".to_string(), y: "2".to_string() }; + || { //~ ERROR closure may outlive the current block, but it borrows `p` + let x = &mut p.x; + println!("{:?}", p); + } + }; + c(); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr new file mode 100644 index 000000000..ee9238047 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr @@ -0,0 +1,22 @@ +error[E0373]: closure may outlive the current block, but it borrows `p`, which is owned by the current block + --> $DIR/borrowck-3.rs:11:9 + | +LL | || { + | ^^ may outlive borrowed value `p` +LL | let x = &mut p.x; +LL | println!("{:?}", p); + | - `p` is borrowed here + | +note: block requires argument type to outlive `'1` + --> $DIR/borrowck-3.rs:9:9 + | +LL | let mut c = { + | ^^^^^ +help: to force the closure to take ownership of `p` (and any other referenced variables), use the `move` keyword + | +LL | move || { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs new file mode 100644 index 000000000..a2290d850 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs @@ -0,0 +1,20 @@ +// edition:2021 + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} +fn foo () -> impl FnMut()->() { + let mut p = Point {x: 1, y: 2 }; + let mut c = || { + //~^ ERROR closure may outlive the current function, but it borrows `p` + p.x+=5; + println!("{:?}", p); + }; + c +} +fn main() { + let c = foo(); + c(); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr new file mode 100644 index 000000000..46379a381 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr @@ -0,0 +1,22 @@ +error[E0373]: closure may outlive the current function, but it borrows `p`, which is owned by the current function + --> $DIR/borrowck-4.rs:10:17 + | +LL | let mut c = || { + | ^^ may outlive borrowed value `p` +... +LL | println!("{:?}", p); + | - `p` is borrowed here + | +note: closure is returned here + --> $DIR/borrowck-4.rs:15:5 + | +LL | c + | ^ +help: to force the closure to take ownership of `p` (and any other referenced variables), use the `move` keyword + | +LL | let mut c = move || { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs new file mode 100644 index 000000000..5ff7b1242 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs @@ -0,0 +1,26 @@ +// edition:2021 + + + +// Tests that two closures cannot simultaneously have mutable +// and immutable access to the variable. Issue #6801. + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} + +fn a() { + let mut p = Point {x: 3, y:4}; + let c2 = || p.y * 5; + let c1 = || { + //~^ ERROR cannot borrow `p` as mutable because it is also borrowed as immutable + dbg!(&p); + p.x = 4; + }; + drop(c2); +} + +fn main() { +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr new file mode 100644 index 000000000..5f1dae297 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr @@ -0,0 +1,21 @@ +error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-closures-mut-and-imm.rs:17:14 + | +LL | let c2 = || p.y * 5; + | -- --- first borrow occurs due to use of `p.y` in closure + | | + | immutable borrow occurs here +LL | let c1 = || { + | ^^ mutable borrow occurs here +LL | +LL | dbg!(&p); + | - second borrow occurs due to use of `p` in closure +LL | p.x = 4; + | --- capture is mutable because of use here +LL | }; +LL | drop(c2); + | -- immutable borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/box.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/box.rs new file mode 100644 index 000000000..a110fa4e2 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/box.rs @@ -0,0 +1,64 @@ +// edition:2021 + +// Test borrow checker when we precise capture when using boxes + +struct MetaData { x: String, name: String } +struct Data { m: MetaData } +struct BoxedData(Box); +struct EvenMoreBoxedData(Box); + +// Check diagnostics when the same path is mutated both inside and outside the closure +fn box_1() { + let m = MetaData { x: format!("x"), name: format!("name") }; + let d = Data { m }; + let b = BoxedData(Box::new(d)); + let mut e = EvenMoreBoxedData(Box::new(b)); + + let mut c = || { + e.0.0.m.x = format!("not-x"); + }; + + e.0.0.m.x = format!("not-x"); + //~^ ERROR: cannot assign to `e.0.0.m.x` because it is borrowed + c(); +} + +// Check diagnostics when a path is mutated inside a closure while attempting to read it outside +// the closure. +fn box_2() { + let m = MetaData { x: format!("x"), name: format!("name") }; + let d = Data { m }; + let b = BoxedData(Box::new(d)); + let mut e = EvenMoreBoxedData(Box::new(b)); + + let mut c = || { + e.0.0.m.x = format!("not-x"); + }; + + println!("{}", e.0.0.m.x); + //~^ ERROR: cannot borrow `e.0.0.m.x` as immutable because it is also borrowed as mutable + c(); +} + +// Check diagnostics when a path is read inside a closure while attempting to mutate it outside +// the closure. +fn box_3() { + let m = MetaData { x: format!("x"), name: format!("name") }; + let d = Data { m }; + let b = BoxedData(Box::new(d)); + let mut e = EvenMoreBoxedData(Box::new(b)); + + let c = || { + println!("{}", e.0.0.m.x); + }; + + e.0.0.m.x = format!("not-x"); + //~^ ERROR: cannot assign to `e.0.0.m.x` because it is borrowed + c(); +} + +fn main() { + box_1(); + box_2(); + box_3(); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/box.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/box.stderr new file mode 100644 index 000000000..f8b178752 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/box.stderr @@ -0,0 +1,48 @@ +error[E0506]: cannot assign to `e.0.0.m.x` because it is borrowed + --> $DIR/box.rs:21:5 + | +LL | let mut c = || { + | -- borrow of `e.0.0.m.x` occurs here +LL | e.0.0.m.x = format!("not-x"); + | --------- borrow occurs due to use in closure +... +LL | e.0.0.m.x = format!("not-x"); + | ^^^^^^^^^ assignment to borrowed `e.0.0.m.x` occurs here +LL | +LL | c(); + | - borrow later used here + +error[E0502]: cannot borrow `e.0.0.m.x` as immutable because it is also borrowed as mutable + --> $DIR/box.rs:38:20 + | +LL | let mut c = || { + | -- mutable borrow occurs here +LL | e.0.0.m.x = format!("not-x"); + | --------- first borrow occurs due to use of `e.0.0.m.x` in closure +... +LL | println!("{}", e.0.0.m.x); + | ^^^^^^^^^ immutable borrow occurs here +LL | +LL | c(); + | - mutable borrow later used here + | + = 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[E0506]: cannot assign to `e.0.0.m.x` because it is borrowed + --> $DIR/box.rs:55:5 + | +LL | let c = || { + | -- borrow of `e.0.0.m.x` occurs here +LL | println!("{}", e.0.0.m.x); + | --------- borrow occurs due to use in closure +... +LL | e.0.0.m.x = format!("not-x"); + | ^^^^^^^^^ assignment to borrowed `e.0.0.m.x` occurs here +LL | +LL | c(); + | - borrow later used here + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0502, E0506. +For more information about an error, try `rustc --explain E0502`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.rs new file mode 100644 index 000000000..77effcb00 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.rs @@ -0,0 +1,19 @@ +// edition:2021 + +// Test that if we deref an immutable borrow to access a Place, +// then we can't mutate the final place. + +fn main() { + let mut x = (format!(""), format!("X2")); + let mut y = (&x, "Y"); + let z = (&mut y, "Z"); + + // `x.0` is mutable but we access `x` via `*z.0.0`, which is an immutable reference and + // therefore can't be mutated. + let mut c = || { + //~^ ERROR: cannot borrow `*z.0.0` as mutable, as it is behind a `&` reference + z.0.0.0 = format!("X1"); + }; + + c(); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr new file mode 100644 index 000000000..38c530b80 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr @@ -0,0 +1,12 @@ +error[E0596]: cannot borrow `*z.0.0` as mutable, as it is behind a `&` reference + --> $DIR/cant-mutate-imm-borrow.rs:13:17 + | +LL | let mut c = || { + | ^^ cannot borrow as mutable +LL | +LL | z.0.0.0 = format!("X1"); + | ------- mutable borrow occurs due to use of `*z.0.0` in closure + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.rs new file mode 100644 index 000000000..25ee9a149 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.rs @@ -0,0 +1,34 @@ +// edition:2021 + +// Ensure that diagnostics for mutability error (because the root variable +// isn't mutable) work with `capture_disjoint_fields` enabled. + +fn mut_error_struct() { + let x = (10, 10); + let y = (x, 10); + let z = (y, 10); + + let mut c = || { + z.0.0.0 = 20; + //~^ ERROR: cannot assign to `z.0.0.0`, as it is not declared as mutable + }; + + c(); +} + +fn mut_error_box() { + let x = (10, 10); + let bx = Box::new(x); + + let mut c = || { + bx.0 = 20; + //~^ ERROR: cannot assign to `*bx.0`, as it is not declared as mutable + }; + + c(); +} + +fn main() { + mut_error_struct(); + mut_error_box(); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.stderr new file mode 100644 index 000000000..98414fa8a --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.stderr @@ -0,0 +1,21 @@ +error[E0594]: cannot assign to `z.0.0.0`, as it is not declared as mutable + --> $DIR/cant-mutate-imm.rs:12:9 + | +LL | let z = (y, 10); + | - help: consider changing this to be mutable: `mut z` +... +LL | z.0.0.0 = 20; + | ^^^^^^^^^^^^ cannot assign + +error[E0594]: cannot assign to `*bx.0`, as it is not declared as mutable + --> $DIR/cant-mutate-imm.rs:24:9 + | +LL | let bx = Box::new(x); + | -- help: consider changing this to be mutable: `mut bx` +... +LL | bx.0 = 20; + | ^^^^^^^^^ cannot assign + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.rs new file mode 100644 index 000000000..f3be542e4 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.rs @@ -0,0 +1,13 @@ +// edition:2021 + +// Test that array access is not stored as part of closure kind origin + +fn expect_fn(_f: F) {} + +fn main() { + let s = [format!("s"), format!("s")]; + let c = || { //~ ERROR expected a closure that implements the `Fn` + let [_, _s] = s; + }; + expect_fn(c); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr new file mode 100644 index 000000000..309c63e52 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr @@ -0,0 +1,22 @@ +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` + --> $DIR/closure-origin-array-diagnostics.rs:9:13 + | +LL | let c = || { + | ^^ this closure implements `FnOnce`, not `Fn` +LL | let [_, _s] = s; + | - closure is `FnOnce` because it moves the variable `s` out of its environment +LL | }; +LL | expect_fn(c); + | --------- - the requirement to implement `Fn` derives from here + | | + | required by a bound introduced by this call + | +note: required by a bound in `expect_fn` + --> $DIR/closure-origin-array-diagnostics.rs:5:17 + | +LL | fn expect_fn(_f: F) {} + | ^^^^ required by this bound in `expect_fn` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs new file mode 100644 index 000000000..aa85b55b1 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs @@ -0,0 +1,27 @@ +// edition:2021 + +// Check that precise paths are being reported back in the error message. + +enum MultiVariant { + Point(i32, i32), + Meta(i32) +} + +fn main() { + let mut point = MultiVariant::Point(10, -10,); + + let mut meta = MultiVariant::Meta(1); + + let c = || { + if let MultiVariant::Point(ref mut x, _) = point { + *x += 1; + } + + if let MultiVariant::Meta(ref mut v) = meta { + *v += 1; + } + }; + + let a = c; + let b = c; //~ ERROR use of moved value: `c` [E0382] +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr new file mode 100644 index 000000000..83d282aad --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr @@ -0,0 +1,21 @@ +error[E0382]: use of moved value: `c` + --> $DIR/closure-origin-multi-variant-diagnostics.rs:26:13 + | +LL | let a = c; + | - value moved here +LL | let b = c; + | ^ value used here after move + | +note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `point.0` out of its environment + --> $DIR/closure-origin-multi-variant-diagnostics.rs:16:52 + | +LL | if let MultiVariant::Point(ref mut x, _) = point { + | ^^^^^ +help: consider mutably borrowing `c` + | +LL | let a = &mut c; + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs new file mode 100644 index 000000000..bedb103cc --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs @@ -0,0 +1,18 @@ +// edition:2021 + + +enum SingleVariant { + Point(i32, i32), +} + +fn main() { + let mut point = SingleVariant::Point(10, -10); + + let c = || { + let SingleVariant::Point(ref mut x, _) = point; + *x += 1; + }; + + let b = c; + let a = c; //~ ERROR use of moved value: `c` [E0382] +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr new file mode 100644 index 000000000..46323b752 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr @@ -0,0 +1,21 @@ +error[E0382]: use of moved value: `c` + --> $DIR/closure-origin-single-variant-diagnostics.rs:17:13 + | +LL | let b = c; + | - value moved here +LL | let a = c; + | ^ value used here after move + | +note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `point.0` out of its environment + --> $DIR/closure-origin-single-variant-diagnostics.rs:12:50 + | +LL | let SingleVariant::Point(ref mut x, _) = point; + | ^^^^^ +help: consider mutably borrowing `c` + | +LL | let b = &mut c; + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs new file mode 100644 index 000000000..3277a83c4 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs @@ -0,0 +1,22 @@ +// edition:2021 + +// Check that precise paths are being reported back in the error message. + +struct Y { + y: X +} + +struct X { + a: u32, + b: u32, +} + +fn main() { + let mut x = Y { y: X { a: 5, b: 0 } }; + let hello = || { + x.y.a += 1; + }; + + let b = hello; + let c = hello; //~ ERROR use of moved value: `hello` [E0382] +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr new file mode 100644 index 000000000..25029cc7b --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr @@ -0,0 +1,21 @@ +error[E0382]: use of moved value: `hello` + --> $DIR/closure-origin-struct-diagnostics.rs:21:13 + | +LL | let b = hello; + | ----- value moved here +LL | let c = hello; + | ^^^^^ value used here after move + | +note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `x.y.a` out of its environment + --> $DIR/closure-origin-struct-diagnostics.rs:17:9 + | +LL | x.y.a += 1; + | ^^^^^ +help: consider mutably borrowing `hello` + | +LL | let b = &mut hello; + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs new file mode 100644 index 000000000..dc3a57ae7 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs @@ -0,0 +1,13 @@ +// edition:2021 + +// Check that precise paths are being reported back in the error message. + +fn main() { + let mut x = (5, 0); + let hello = || { + x.0 += 1; + }; + + let b = hello; + let c = hello; //~ ERROR use of moved value: `hello` [E0382] +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr new file mode 100644 index 000000000..06ef7baf9 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr @@ -0,0 +1,21 @@ +error[E0382]: use of moved value: `hello` + --> $DIR/closure-origin-tuple-diagnostics-1.rs:12:13 + | +LL | let b = hello; + | ----- value moved here +LL | let c = hello; + | ^^^^^ value used here after move + | +note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `x.0` out of its environment + --> $DIR/closure-origin-tuple-diagnostics-1.rs:8:9 + | +LL | x.0 += 1; + | ^^^ +help: consider mutably borrowing `hello` + | +LL | let b = &mut hello; + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs new file mode 100644 index 000000000..fa1328013 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs @@ -0,0 +1,13 @@ +// edition:2021 + +struct S(String, String); + +fn expect_fn(_f: F) {} + +fn main() { + let s = S(format!("s"), format!("s")); + let c = || { //~ ERROR expected a closure that implements the `Fn` + let s = s.1; + }; + expect_fn(c); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr new file mode 100644 index 000000000..3e77635f9 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr @@ -0,0 +1,22 @@ +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` + --> $DIR/closure-origin-tuple-diagnostics.rs:9:13 + | +LL | let c = || { + | ^^ this closure implements `FnOnce`, not `Fn` +LL | let s = s.1; + | --- closure is `FnOnce` because it moves the variable `s.1` out of its environment +LL | }; +LL | expect_fn(c); + | --------- - the requirement to implement `Fn` derives from here + | | + | required by a bound introduced by this call + | +note: required by a bound in `expect_fn` + --> $DIR/closure-origin-tuple-diagnostics.rs:5:17 + | +LL | fn expect_fn(_f: F) {} + | ^^^^ required by this bound in `expect_fn` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/liveness.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/liveness.rs new file mode 100644 index 000000000..3399bc001 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/liveness.rs @@ -0,0 +1,92 @@ +// edition:2021 + +// check-pass +#![allow(unreachable_code)] +#![warn(unused)] +#![allow(dead_code)] + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} + +pub fn f() { + let mut a = 1; + let mut c = Point{ x:1, y:0 }; + + // Captured by value, but variable is dead on entry. + (move || { + // This will not trigger a warning for unused variable as + // c.x will be treated as a Non-tracked place + c.x = 1; + println!("{}", c.x); + a = 1; //~ WARN value captured by `a` is never read + println!("{}", a); + })(); + + // Read and written to, but never actually used. + (move || { + // This will not trigger a warning for unused variable as + // c.x will be treated as a Non-tracked place + c.x += 1; + a += 1; //~ WARN unused variable: `a` + })(); + + (move || { + println!("{}", c.x); + // Value is read by closure itself on later invocations. + // This will not trigger a warning for unused variable as + // c.x will be treated as a Non-tracked place + c.x += 1; + println!("{}", a); + a += 1; + })(); + let b = Box::new(42); + (move || { + println!("{}", c.x); + // Never read because this is FnOnce closure. + // This will not trigger a warning for unused variable as + // c.x will be treated as a Non-tracked place + c.x += 1; + println!("{}", a); + a += 1; //~ WARN value assigned to `a` is never read + drop(b); + })(); +} + +#[derive(Debug)] +struct MyStruct<'a> { + x: Option<& 'a str>, + y: i32, +} + +pub fn nested() { + let mut a : Option<& str>; + a = None; + let mut b : Option<& str>; + b = None; + let mut d = MyStruct{ x: None, y: 1}; + let mut e = MyStruct{ x: None, y: 1}; + (|| { + (|| { + // This will not trigger a warning for unused variable as + // d.x will be treated as a Non-tracked place + d.x = Some("d1"); + d.x = Some("d2"); + a = Some("d1"); //~ WARN value assigned to `a` is never read + a = Some("d2"); + })(); + (move || { + // This will not trigger a warning for unused variable as + //e.x will be treated as a Non-tracked place + e.x = Some("e1"); + e.x = Some("e2"); + b = Some("e1"); //~ WARN value assigned to `b` is never read + //~| WARN unused variable: `b` + b = Some("e2"); //~ WARN value assigned to `b` is never read + })(); + })(); +} + +fn main() {} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr new file mode 100644 index 000000000..cf414adc0 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr @@ -0,0 +1,65 @@ +warning: value captured by `a` is never read + --> $DIR/liveness.rs:24:9 + | +LL | a = 1; + | ^ + | + = help: did you mean to capture by reference instead? +note: the lint level is defined here + --> $DIR/liveness.rs:5:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]` + +warning: unused variable: `a` + --> $DIR/liveness.rs:33:9 + | +LL | a += 1; + | ^ + | + = help: did you mean to capture by reference instead? + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: value assigned to `a` is never read + --> $DIR/liveness.rs:53:9 + | +LL | a += 1; + | ^ + | + = help: maybe it is overwritten before being read? + +warning: value assigned to `a` is never read + --> $DIR/liveness.rs:77:13 + | +LL | a = Some("d1"); + | ^ + | + = help: maybe it is overwritten before being read? + +warning: value assigned to `b` is never read + --> $DIR/liveness.rs:85:13 + | +LL | b = Some("e1"); + | ^ + | + = help: maybe it is overwritten before being read? + +warning: value assigned to `b` is never read + --> $DIR/liveness.rs:87:13 + | +LL | b = Some("e2"); + | ^ + | + = help: maybe it is overwritten before being read? + +warning: unused variable: `b` + --> $DIR/liveness.rs:85:13 + | +LL | b = Some("e1"); + | ^ + | + = help: did you mean to capture by reference instead? + +warning: 7 warnings emitted + diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs new file mode 100644 index 000000000..465c9476b --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs @@ -0,0 +1,43 @@ +// edition:2021 + +// check-pass +#![warn(unused)] +#![allow(dead_code)] + +#[derive(Debug)] +struct MyStruct { + a: i32, + b: i32, +} + +pub fn unintentional_copy_one() { + let mut a = 1; + let mut last = MyStruct{ a: 1, b: 1}; + let mut f = move |s| { + // This will not trigger a warning for unused variable + // as last.a will be treated as a Non-tracked place + last.a = s; + a = s; + //~^ WARN value assigned to `a` is never read + //~| WARN unused variable: `a` + }; + f(2); + f(3); + f(4); +} + +pub fn unintentional_copy_two() { + let mut a = 1; + let mut sum = MyStruct{ a: 1, b: 0}; + (1..10).for_each(move |x| { + // This will not trigger a warning for unused variable + // as sum.b will be treated as a Non-tracked place + sum.b += x; + a += x; //~ WARN unused variable: `a` + }); +} + +fn main() { + unintentional_copy_one(); + unintentional_copy_two(); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr new file mode 100644 index 000000000..0410de4c7 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr @@ -0,0 +1,33 @@ +warning: value assigned to `a` is never read + --> $DIR/liveness_unintentional_copy.rs:20:9 + | +LL | a = s; + | ^ + | + = help: maybe it is overwritten before being read? +note: the lint level is defined here + --> $DIR/liveness_unintentional_copy.rs:4:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]` + +warning: unused variable: `a` + --> $DIR/liveness_unintentional_copy.rs:20:9 + | +LL | a = s; + | ^ + | + = help: did you mean to capture by reference instead? + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: unused variable: `a` + --> $DIR/liveness_unintentional_copy.rs:36:9 + | +LL | a += x; + | ^ + | + = help: did you mean to capture by reference instead? + +warning: 3 warnings emitted + diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.rs new file mode 100644 index 000000000..fa73ff23f --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.rs @@ -0,0 +1,28 @@ +// edition:2021 + +// Test that when a borrow checker diagnostics are emitted, it's as precise +// as the capture by the closure. + +#![allow(unused)] + +struct Point { + x: i32, + y: i32, +} +struct Wrapper { + p: Point, +} + +fn main() { + let mut w = Wrapper { p: Point { x: 10, y: 10 } }; + + let mut c = || { + w.p.x += 20; + }; + + let py = &mut w.p.x; + //~^ ERROR: cannot borrow `w.p.x` as mutable more than once at a time + c(); + + *py = 20 +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr new file mode 100644 index 000000000..ac4c9c937 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr @@ -0,0 +1,17 @@ +error[E0499]: cannot borrow `w.p.x` as mutable more than once at a time + --> $DIR/multilevel-path.rs:23:14 + | +LL | let mut c = || { + | -- first mutable borrow occurs here +LL | w.p.x += 20; + | ----- first borrow occurs due to use of `w.p.x` in closure +... +LL | let py = &mut w.p.x; + | ^^^^^^^^^^ second mutable borrow occurs here +LL | +LL | c(); + | - first borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/mut_ref.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/mut_ref.rs new file mode 100644 index 000000000..3d5a31e8b --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/mut_ref.rs @@ -0,0 +1,37 @@ +// edition:2021 + +// Test that we can't mutate a place if we need to deref an imm-borrow +// to reach it. + +fn imm_mut_ref() { + let mut x = String::new(); + let y = String::new(); + let mref_x = &mut x; + let ref_mref_x = &mref_x; + + let c = || { + //~^ ERROR: cannot borrow `**ref_mref_x` as mutable, as it is behind a `&` reference + **ref_mref_x = y; + }; + + c(); +} + +fn mut_imm_ref() { + let x = String::new(); + let y = String::new(); + let mut ref_x = &x; + let mref_ref_x = &mut ref_x; + + let c = || { + //~^ ERROR: cannot borrow `**mref_ref_x` as mutable, as it is behind a `&` reference + **mref_ref_x = y; + }; + + c(); +} + +fn main() { + imm_mut_ref(); + mut_imm_ref(); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr new file mode 100644 index 000000000..95f36fc04 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr @@ -0,0 +1,26 @@ +error[E0596]: cannot borrow `**ref_mref_x` as mutable, as it is behind a `&` reference + --> $DIR/mut_ref.rs:12:13 + | +LL | let c = || { + | ^^ `ref_mref_x` is a `&` reference, so the data it refers to cannot be borrowed as mutable +LL | +LL | **ref_mref_x = y; + | ------------ mutable borrow occurs due to use of `**ref_mref_x` in closure + | +help: consider changing this to be a mutable reference + | +LL | let ref_mref_x = &mut mref_x; + | ~~~~~~~~~~~ + +error[E0596]: cannot borrow `**mref_ref_x` as mutable, as it is behind a `&` reference + --> $DIR/mut_ref.rs:26:13 + | +LL | let c = || { + | ^^ cannot borrow as mutable +LL | +LL | **mref_ref_x = y; + | ------------ mutable borrow occurs due to use of `**mref_ref_x` in closure + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs new file mode 100644 index 000000000..1488f3296 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs @@ -0,0 +1,32 @@ +// edition:2021 + +// Given how the closure desugaring is implemented (at least at the time of writing this test), +// we don't need to truncate the captured path to a reference into a packed-struct if the field +// being referenced will be moved into the closure, since it's safe to move out a field from a +// packed-struct. +// +// However to avoid surprises for the user, or issues when the closure is +// inlined we will truncate the capture to access just the struct regardless of if the field +// might get moved into the closure. +// +// It is possible for someone to try writing the code that relies on the desugaring to create a ref +// into a packed-struct. Here we test that the compiler still detects that case. +fn test_missing_unsafe_warning_on_repr_packed() { + #[repr(packed)] + struct Foo { x: String } + + let foo = Foo { x: String::new() }; + + let c = || { + println!("{}", foo.x); + //~^ ERROR: reference to packed field is unaligned + //~| WARNING: this was previously accepted by the compiler but is being phased out + let _z = foo.x; + }; + + c(); +} + +fn main() { + test_missing_unsafe_warning_on_repr_packed(); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr new file mode 100644 index 000000000..508c4b911 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr @@ -0,0 +1,29 @@ +error: reference to packed field is unaligned + --> $DIR/repr_packed.rs:21:24 + | +LL | println!("{}", foo.x); + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + = note: `#[deny(unaligned_references)]` on by default + = 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 + +Future incompatibility report: Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/repr_packed.rs:21:24 + | +LL | println!("{}", foo.x); + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + = note: `#[deny(unaligned_references)]` on by default + = 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) + diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.rs new file mode 100644 index 000000000..ed2d9a3de --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.rs @@ -0,0 +1,25 @@ +// edition:2021 + +// Test that borrow checker error is accurate and that min capture pass of the +// closure analysis is working as expected. + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} + +fn main() { + let mut p = Point { x: 10, y: 20 }; + + // `p` is captured via mutable borrow. + let mut c = || { + p.x += 10; + println!("{:?}", p); + }; + + + println!("{:?}", p); + //~^ ERROR: cannot borrow `p` as immutable because it is also borrowed as mutable + c(); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr new file mode 100644 index 000000000..06157b2af --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr @@ -0,0 +1,21 @@ +error[E0502]: cannot borrow `p` as immutable because it is also borrowed as mutable + --> $DIR/simple-struct-min-capture.rs:22:22 + | +LL | let mut c = || { + | -- mutable borrow occurs here +LL | p.x += 10; + | --- capture is mutable because of use here +LL | println!("{:?}", p); + | - first borrow occurs due to use of `p` in closure +... +LL | println!("{:?}", p); + | ^ immutable borrow occurs here +LL | +LL | c(); + | - mutable borrow later used here + | + = 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 E0502`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/union.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/union.rs new file mode 100644 index 000000000..46b54846e --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/union.rs @@ -0,0 +1,25 @@ +// edition:2021 + +// Test that we point to the correct location that results a union being captured. +// Union is special because it can't be disjointly captured. + +union A { + y: u32, + x: (), +} + +fn main() { + let mut a = A { y: 1 }; + let mut c = || { + //~^ borrow of `a.y` occurs here + let _ = unsafe { &a.y }; + let _ = &mut a; + //~^ borrow occurs due to use in closure + let _ = unsafe { &mut a.y }; + }; + a.y = 1; + //~^ cannot assign to `a.y` because it is borrowed [E0506] + //~| assignment to borrowed `a.y` occurs here + c(); + //~^ borrow later used here +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/union.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/union.stderr new file mode 100644 index 000000000..7c34e2336 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/union.stderr @@ -0,0 +1,18 @@ +error[E0506]: cannot assign to `a.y` because it is borrowed + --> $DIR/union.rs:20:5 + | +LL | let mut c = || { + | -- borrow of `a.y` occurs here +... +LL | let _ = &mut a; + | - borrow occurs due to use in closure +... +LL | a.y = 1; + | ^^^^^^^ assignment to borrowed `a.y` occurs here +... +LL | c(); + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. -- cgit v1.2.3