Skip to content

Commit 1373f98

Browse files
committed
Test cases for handling mutable references
1 parent 3488082 commit 1373f98

File tree

8 files changed

+245
-0
lines changed

8 files changed

+245
-0
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Test that if we deref an immutable borrow to access a Place,
2+
// then we can't mutate the final place.
3+
4+
#![feature(capture_disjoint_fields)]
5+
//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
6+
7+
fn main() {
8+
let mut x = (format!(""), format!("X2"));
9+
let mut y = (&x, "Y");
10+
let z = (&mut y, "Z");
11+
12+
// `x.0` is mutable but we access `x` via `z.0.0`, which is an immutable reference and
13+
// therefore can't be mutated.
14+
let mut c = || {
15+
//~^ ERROR: cannot borrow `z.0.0.0` as mutable, as it is behind a `&` reference
16+
z.0.0.0 = format!("X1");
17+
//~^ ERROR: cannot assign to `z`, as it is not declared as mutable
18+
};
19+
20+
c();
21+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/cant-mutate-imm-borrow.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[E0594]: cannot assign to `z`, as it is not declared as mutable
11+
--> $DIR/cant-mutate-imm-borrow.rs:16:9
12+
|
13+
LL | let z = (&mut y, "Z");
14+
| - help: consider changing this to be mutable: `mut z`
15+
...
16+
LL | z.0.0.0 = format!("X1");
17+
| ^^^^^^^ cannot assign
18+
19+
error[E0596]: cannot borrow `z.0.0.0` as mutable, as it is behind a `&` reference
20+
--> $DIR/cant-mutate-imm-borrow.rs:14:17
21+
|
22+
LL | let mut c = || {
23+
| ^^ cannot borrow as mutable
24+
LL |
25+
LL | z.0.0.0 = format!("X1");
26+
| - mutable borrow occurs due to use of `z.0.0.0` in closure
27+
28+
error: aborting due to 2 previous errors; 1 warning emitted
29+
30+
Some errors have detailed explanations: E0594, E0596.
31+
For more information about an error, try `rustc --explain E0594`.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Test that we can't mutate a place if we need to deref an imm-borrow
2+
// to reach it.
3+
4+
#![feature(capture_disjoint_fields)]
5+
//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
6+
7+
fn imm_mut_ref() {
8+
let mut x = String::new();
9+
let y = String::new();
10+
let mref_x = &mut x;
11+
let ref_mref_x = &mref_x;
12+
13+
let c = || {
14+
//~^ ERROR: cannot borrow `**ref_mref_x` as mutable, as it is behind a `&` reference
15+
**ref_mref_x = y;
16+
//~^ERROR: cannot assign to `ref_mref_x`, as it is not declared as mutable
17+
};
18+
19+
c();
20+
}
21+
22+
fn mut_imm_ref() {
23+
let x = String::new();
24+
let y = String::new();
25+
let mut ref_x = &x;
26+
let mref_ref_x = &mut ref_x;
27+
28+
let c = || {
29+
//~^ ERROR: cannot borrow `**mref_ref_x` as mutable, as it is behind a `&` reference
30+
**mref_ref_x = y;
31+
//~^ERROR: cannot assign to `mref_ref_x`, as it is not declared as mutable
32+
};
33+
34+
c();
35+
}
36+
37+
fn main() {
38+
imm_mut_ref();
39+
mut_imm_ref();
40+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/mut_ref.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[E0594]: cannot assign to `ref_mref_x`, as it is not declared as mutable
11+
--> $DIR/mut_ref.rs:15:9
12+
|
13+
LL | let ref_mref_x = &mref_x;
14+
| ---------- help: consider changing this to be mutable: `mut ref_mref_x`
15+
...
16+
LL | **ref_mref_x = y;
17+
| ^^^^^^^^^^^^ cannot assign
18+
19+
error[E0596]: cannot borrow `**ref_mref_x` as mutable, as it is behind a `&` reference
20+
--> $DIR/mut_ref.rs:13:13
21+
|
22+
LL | let ref_mref_x = &mref_x;
23+
| ------- help: consider changing this to be a mutable reference: `&mut mref_x`
24+
LL |
25+
LL | let c = || {
26+
| ^^ `ref_mref_x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
27+
LL |
28+
LL | **ref_mref_x = y;
29+
| ---------- mutable borrow occurs due to use of `**ref_mref_x` in closure
30+
31+
error[E0594]: cannot assign to `mref_ref_x`, as it is not declared as mutable
32+
--> $DIR/mut_ref.rs:30:9
33+
|
34+
LL | let mref_ref_x = &mut ref_x;
35+
| ---------- help: consider changing this to be mutable: `mut mref_ref_x`
36+
...
37+
LL | **mref_ref_x = y;
38+
| ^^^^^^^^^^^^ cannot assign
39+
40+
error[E0596]: cannot borrow `**mref_ref_x` as mutable, as it is behind a `&` reference
41+
--> $DIR/mut_ref.rs:28:13
42+
|
43+
LL | let c = || {
44+
| ^^ cannot borrow as mutable
45+
LL |
46+
LL | **mref_ref_x = y;
47+
| ---------- mutable borrow occurs due to use of `**mref_ref_x` in closure
48+
49+
error: aborting due to 4 previous errors; 1 warning emitted
50+
51+
Some errors have detailed explanations: E0594, E0596.
52+
For more information about an error, try `rustc --explain E0594`.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// run-pass
2+
3+
// Test that we can mutate a place through a mut-borrow
4+
// that is captured by the closure
5+
6+
#![feature(capture_disjoint_fields)]
7+
//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
8+
9+
// Check that we can mutate when one deref is required
10+
fn mut_ref_1() {
11+
let mut x = String::new();
12+
let rx = &mut x;
13+
14+
let mut c = || {
15+
*rx = String::new();
16+
};
17+
18+
c();
19+
}
20+
21+
// Similar example as mut_ref_1, we don't deref the imm-borrow here,
22+
// and so we are allowed to mutate.
23+
fn mut_ref_2() {
24+
let x = String::new();
25+
let y = String::new();
26+
let mut ref_x = &x;
27+
let m_ref_x = &mut ref_x;
28+
29+
let mut c = || {
30+
*m_ref_x = &y;
31+
};
32+
33+
c();
34+
}
35+
36+
// Check that we can mutate when multiple derefs of mut-borrows are required to reach
37+
// the target place.
38+
// It works because all derefs are mutable, if either of them was an immutable
39+
// borrow, then we would not be able to deref.
40+
fn mut_mut_ref() {
41+
let mut x = String::new();
42+
let mut mref_x = &mut x;
43+
let m_mref_x = &mut mref_x;
44+
45+
let mut c = || {
46+
**m_mref_x = String::new();
47+
};
48+
49+
c();
50+
}
51+
52+
fn main() {
53+
mut_ref_1();
54+
mut_ref_2();
55+
mut_mut_ref();
56+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/mut_ref.rs:6: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+
warning: 1 warning emitted
11+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// run-pass
2+
3+
// Test that we can mutate a place through a mut-borrow
4+
// that is captured by the closure
5+
//
6+
// More specifically we test that the if the mutable reference isn't root variable of a capture
7+
// but rather accessed while acessing the precise capture.
8+
9+
#![feature(capture_disjoint_fields)]
10+
//~^ WARNING: the feature `capture_disjoint_fields` is incomplete
11+
12+
fn main() {
13+
let mut t = (10, 10);
14+
15+
let t1 = (&mut t, 10);
16+
17+
let mut c = || {
18+
// Mutable because (*t.0) is mutable
19+
t1.0.0 += 10;
20+
};
21+
22+
c();
23+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/mut_ref_struct_mem.rs:9: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+
warning: 1 warning emitted
11+

0 commit comments

Comments
 (0)