Skip to content

Commit 01df563

Browse files
committed
Test cases for RFC 2229
1 parent 237ad12 commit 01df563

28 files changed

+914
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Test that arrays are completely captured by closures by relying on the borrow check diagnostics
2+
3+
#![feature(capture_disjoint_fields)]
4+
//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
5+
6+
fn arrays_1() {
7+
let mut arr = [1, 2, 3, 4, 5];
8+
9+
let mut c = || {
10+
arr[0] += 10;
11+
};
12+
13+
// c will capture `arr` completely, therefore another index into the
14+
// array can't be modified here
15+
arr[1] += 10;
16+
//~^ ERROR: cannot use `arr` because it was mutably borrowed
17+
//~| ERROR: cannot use `arr[_]` because it was mutably borrowed
18+
c();
19+
}
20+
21+
fn arrays_2() {
22+
let mut arr = [1, 2, 3, 4, 5];
23+
24+
let c = || {
25+
println!("{:#?}", &arr[3..4]);
26+
};
27+
28+
// c will capture `arr` completely, therefore another index into the
29+
// array can't be modified here
30+
arr[1] += 10;
31+
//~^ ERROR: cannot assign to `arr[_]` because it is borrowed
32+
c();
33+
}
34+
35+
fn arrays_3() {
36+
let mut arr = [1, 2, 3, 4, 5];
37+
38+
let c = || {
39+
println!("{}", arr[3]);
40+
};
41+
42+
// c will capture `arr` completely, therefore another index into the
43+
// array can't be modified here
44+
arr[1] += 10;
45+
//~^ ERROR: cannot assign to `arr[_]` because it is borrowed
46+
c();
47+
}
48+
49+
fn arrays_4() {
50+
let mut arr = [1, 2, 3, 4, 5];
51+
52+
let mut c = || {
53+
arr[1] += 10;
54+
};
55+
56+
// c will capture `arr` completely, therefore we cannot borrow another index
57+
// into the array.
58+
println!("{}", arr[3]);
59+
//~^ ERROR: cannot use `arr` because it was mutably borrowed
60+
//~| ERROR: cannot borrow `arr[_]` as immutable because it is also borrowed as mutable
61+
62+
c();
63+
}
64+
65+
fn arrays_5() {
66+
let mut arr = [1, 2, 3, 4, 5];
67+
68+
let mut c = || {
69+
arr[1] += 10;
70+
};
71+
72+
// c will capture `arr` completely, therefore we cannot borrow other indecies
73+
// into the array.
74+
println!("{:#?}", &arr[3..2]);
75+
//~^ ERROR: cannot borrow `arr` as immutable because it is also borrowed as mutable
76+
77+
c();
78+
}
79+
80+
fn main() {
81+
arrays_1();
82+
arrays_2();
83+
arrays_3();
84+
arrays_4();
85+
arrays_5();
86+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/arrays.rs:3:12
3+
|
4+
LL | #![feature(capture_disjoint_fields)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(incomplete_features)]` on by default
8+
= note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
9+
10+
error[E0503]: cannot use `arr` because it was mutably borrowed
11+
--> $DIR/arrays.rs:15:5
12+
|
13+
LL | let mut c = || {
14+
| -- borrow of `arr` occurs here
15+
LL | arr[0] += 10;
16+
| --- borrow occurs due to use of `arr` in closure
17+
...
18+
LL | arr[1] += 10;
19+
| ^^^^^^ use of borrowed `arr`
20+
...
21+
LL | c();
22+
| - borrow later used here
23+
24+
error[E0503]: cannot use `arr[_]` because it was mutably borrowed
25+
--> $DIR/arrays.rs:15:5
26+
|
27+
LL | let mut c = || {
28+
| -- borrow of `arr` occurs here
29+
LL | arr[0] += 10;
30+
| --- borrow occurs due to use of `arr` in closure
31+
...
32+
LL | arr[1] += 10;
33+
| ^^^^^^^^^^^^ use of borrowed `arr`
34+
...
35+
LL | c();
36+
| - borrow later used here
37+
38+
error[E0506]: cannot assign to `arr[_]` because it is borrowed
39+
--> $DIR/arrays.rs:30:5
40+
|
41+
LL | let c = || {
42+
| -- borrow of `arr[_]` occurs here
43+
LL | println!("{:#?}", &arr[3..4]);
44+
| --- borrow occurs due to use in closure
45+
...
46+
LL | arr[1] += 10;
47+
| ^^^^^^^^^^^^ assignment to borrowed `arr[_]` occurs here
48+
LL |
49+
LL | c();
50+
| - borrow later used here
51+
52+
error[E0506]: cannot assign to `arr[_]` because it is borrowed
53+
--> $DIR/arrays.rs:44:5
54+
|
55+
LL | let c = || {
56+
| -- borrow of `arr[_]` occurs here
57+
LL | println!("{}", arr[3]);
58+
| --- borrow occurs due to use in closure
59+
...
60+
LL | arr[1] += 10;
61+
| ^^^^^^^^^^^^ assignment to borrowed `arr[_]` occurs here
62+
LL |
63+
LL | c();
64+
| - borrow later used here
65+
66+
error[E0503]: cannot use `arr` because it was mutably borrowed
67+
--> $DIR/arrays.rs:58:20
68+
|
69+
LL | let mut c = || {
70+
| -- borrow of `arr` occurs here
71+
LL | arr[1] += 10;
72+
| --- borrow occurs due to use of `arr` in closure
73+
...
74+
LL | println!("{}", arr[3]);
75+
| ^^^^^^ use of borrowed `arr`
76+
...
77+
LL | c();
78+
| - borrow later used here
79+
80+
error[E0502]: cannot borrow `arr[_]` as immutable because it is also borrowed as mutable
81+
--> $DIR/arrays.rs:58:20
82+
|
83+
LL | let mut c = || {
84+
| -- mutable borrow occurs here
85+
LL | arr[1] += 10;
86+
| --- first borrow occurs due to use of `arr` in closure
87+
...
88+
LL | println!("{}", arr[3]);
89+
| ^^^^^^ immutable borrow occurs here
90+
...
91+
LL | c();
92+
| - mutable borrow later used here
93+
94+
error[E0502]: cannot borrow `arr` as immutable because it is also borrowed as mutable
95+
--> $DIR/arrays.rs:74:24
96+
|
97+
LL | let mut c = || {
98+
| -- mutable borrow occurs here
99+
LL | arr[1] += 10;
100+
| --- first borrow occurs due to use of `arr` in closure
101+
...
102+
LL | println!("{:#?}", &arr[3..2]);
103+
| ^^^ immutable borrow occurs here
104+
...
105+
LL | c();
106+
| - mutable borrow later used here
107+
108+
error: aborting due to 7 previous errors; 1 warning emitted
109+
110+
Some errors have detailed explanations: E0502, E0503, E0506.
111+
For more information about an error, try `rustc --explain E0502`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Test borrow checker when we precise capture when using boxes
2+
3+
#![feature(capture_disjoint_fields)]
4+
//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
5+
6+
struct MetaData { x: String, name: String }
7+
struct Data { m: MetaData }
8+
struct BoxedData(Box<Data>);
9+
struct EvenMoreBoxedData(Box<BoxedData>);
10+
11+
// Check diagnostics when the same path is mutated both inside and outside the closure
12+
fn box_1() {
13+
let m = MetaData { x: format!("x"), name: format!("name") };
14+
let d = Data { m };
15+
let b = BoxedData(Box::new(d));
16+
let mut e = EvenMoreBoxedData(Box::new(b));
17+
18+
let mut c = || {
19+
e.0.0.m.x = format!("not-x");
20+
};
21+
22+
e.0.0.m.x = format!("not-x");
23+
//~^ ERROR: cannot assign to `e.0.0.m.x` because it is borrowed
24+
c();
25+
}
26+
27+
// Check diagnostics when a path is mutated inside a closure while attempting to read it outside
28+
// the closure.
29+
fn box_2() {
30+
let m = MetaData { x: format!("x"), name: format!("name") };
31+
let d = Data { m };
32+
let b = BoxedData(Box::new(d));
33+
let mut e = EvenMoreBoxedData(Box::new(b));
34+
35+
let mut c = || {
36+
e.0.0.m.x = format!("not-x");
37+
};
38+
39+
println!("{}", e.0.0.m.x);
40+
//~^ ERROR: cannot borrow `e.0.0.m.x` as immutable because it is also borrowed as mutable
41+
c();
42+
}
43+
44+
// Check diagnostics when a path is read inside a closure while attempting to mutate it outside
45+
// the closure.
46+
fn box_3() {
47+
let m = MetaData { x: format!("x"), name: format!("name") };
48+
let d = Data { m };
49+
let b = BoxedData(Box::new(d));
50+
let mut e = EvenMoreBoxedData(Box::new(b));
51+
52+
let c = || {
53+
println!("{}", e.0.0.m.x);
54+
};
55+
56+
e.0.0.m.x = format!("not-x");
57+
//~^ ERROR: cannot assign to `e.0.0.m.x` because it is borrowed
58+
c();
59+
}
60+
61+
fn main() {
62+
box_1();
63+
box_2();
64+
box_3();
65+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/box.rs:3:12
3+
|
4+
LL | #![feature(capture_disjoint_fields)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(incomplete_features)]` on by default
8+
= note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
9+
10+
error[E0506]: cannot assign to `e.0.0.m.x` because it is borrowed
11+
--> $DIR/box.rs:22:5
12+
|
13+
LL | let mut c = || {
14+
| -- borrow of `e.0.0.m.x` occurs here
15+
LL | e.0.0.m.x = format!("not-x");
16+
| - borrow occurs due to use in closure
17+
...
18+
LL | e.0.0.m.x = format!("not-x");
19+
| ^^^^^^^^^ assignment to borrowed `e.0.0.m.x` occurs here
20+
LL |
21+
LL | c();
22+
| - borrow later used here
23+
24+
error[E0502]: cannot borrow `e.0.0.m.x` as immutable because it is also borrowed as mutable
25+
--> $DIR/box.rs:39:20
26+
|
27+
LL | let mut c = || {
28+
| -- mutable borrow occurs here
29+
LL | e.0.0.m.x = format!("not-x");
30+
| - first borrow occurs due to use of `e.0.0.m.x` in closure
31+
...
32+
LL | println!("{}", e.0.0.m.x);
33+
| ^^^^^^^^^ immutable borrow occurs here
34+
LL |
35+
LL | c();
36+
| - mutable borrow later used here
37+
38+
error[E0506]: cannot assign to `e.0.0.m.x` because it is borrowed
39+
--> $DIR/box.rs:56:5
40+
|
41+
LL | let c = || {
42+
| -- borrow of `e.0.0.m.x` occurs here
43+
LL | println!("{}", e.0.0.m.x);
44+
| - borrow occurs due to use in closure
45+
...
46+
LL | e.0.0.m.x = format!("not-x");
47+
| ^^^^^^^^^ assignment to borrowed `e.0.0.m.x` occurs here
48+
LL |
49+
LL | c();
50+
| - borrow later used here
51+
52+
error: aborting due to 3 previous errors; 1 warning emitted
53+
54+
Some errors have detailed explanations: E0502, E0506.
55+
For more information about an error, try `rustc --explain E0502`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Test that when a borrow checker diagnostics are emitted, it's as precise
2+
// as the capture by the closure.
3+
4+
#![feature(capture_disjoint_fields)]
5+
//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
6+
#![allow(unused)]
7+
8+
struct Point {
9+
x: i32,
10+
y: i32,
11+
}
12+
struct Wrapper {
13+
p: Point,
14+
}
15+
16+
fn main() {
17+
let mut w = Wrapper { p: Point { x: 10, y: 10 } };
18+
19+
let mut c = || {
20+
w.p.x += 20;
21+
};
22+
23+
let py = &mut w.p.x;
24+
//~^ ERROR: cannot borrow `w.p.x` as mutable more than once at a time
25+
c();
26+
27+
*py = 20
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/multilevel-path.rs:4:12
3+
|
4+
LL | #![feature(capture_disjoint_fields)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(incomplete_features)]` on by default
8+
= note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
9+
10+
error[E0499]: cannot borrow `w.p.x` as mutable more than once at a time
11+
--> $DIR/multilevel-path.rs:23:14
12+
|
13+
LL | let mut c = || {
14+
| -- first mutable borrow occurs here
15+
LL | w.p.x += 20;
16+
| - first borrow occurs due to use of `w.p.x` in closure
17+
...
18+
LL | let py = &mut w.p.x;
19+
| ^^^^^^^^^^ second mutable borrow occurs here
20+
LL |
21+
LL | c();
22+
| - first borrow later used here
23+
24+
error: aborting due to previous error; 1 warning emitted
25+
26+
For more information about this error, try `rustc --explain E0499`.

0 commit comments

Comments
 (0)