Skip to content

Commit

Permalink
Test cases for RFC 2229
Browse files Browse the repository at this point in the history
  • Loading branch information
arora-aman committed Dec 11, 2020
1 parent 237ad12 commit 01df563
Show file tree
Hide file tree
Showing 28 changed files with 914 additions and 0 deletions.
86 changes: 86 additions & 0 deletions src/test/ui/closures/2229_closure_analysis/diagnostics/arrays.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Test that arrays are completely captured by closures by relying on the borrow check diagnostics

#![feature(capture_disjoint_fields)]
//~^ WARNING: the feature `capture_disjoint_fields` is incomplete

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 indecies
// 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();
}
111 changes: 111 additions & 0 deletions src/test/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/arrays.rs:3:12
|
LL | #![feature(capture_disjoint_fields)]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information

error[E0503]: cannot use `arr` because it was mutably borrowed
--> $DIR/arrays.rs:15: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:15: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:30: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:44: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:58: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:58: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

error[E0502]: cannot borrow `arr` as immutable because it is also borrowed as mutable
--> $DIR/arrays.rs:74: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; 1 warning emitted

Some errors have detailed explanations: E0502, E0503, E0506.
For more information about an error, try `rustc --explain E0502`.
65 changes: 65 additions & 0 deletions src/test/ui/closures/2229_closure_analysis/diagnostics/box.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Test borrow checker when we precise capture when using boxes

#![feature(capture_disjoint_fields)]
//~^ WARNING: the feature `capture_disjoint_fields` is incomplete

struct MetaData { x: String, name: String }
struct Data { m: MetaData }
struct BoxedData(Box<Data>);
struct EvenMoreBoxedData(Box<BoxedData>);

// 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();
}
55 changes: 55 additions & 0 deletions src/test/ui/closures/2229_closure_analysis/diagnostics/box.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/box.rs:3:12
|
LL | #![feature(capture_disjoint_fields)]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information

error[E0506]: cannot assign to `e.0.0.m.x` because it is borrowed
--> $DIR/box.rs:22: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:39: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

error[E0506]: cannot assign to `e.0.0.m.x` because it is borrowed
--> $DIR/box.rs:56: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; 1 warning emitted

Some errors have detailed explanations: E0502, E0506.
For more information about an error, try `rustc --explain E0502`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Test that when a borrow checker diagnostics are emitted, it's as precise
// as the capture by the closure.

#![feature(capture_disjoint_fields)]
//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
#![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
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/multilevel-path.rs:4:12
|
LL | #![feature(capture_disjoint_fields)]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information

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; 1 warning emitted

For more information about this error, try `rustc --explain E0499`.

0 comments on commit 01df563

Please sign in to comment.