-
-
Notifications
You must be signed in to change notification settings - Fork 14.6k
2229: Fix issues with move closures and mutability #80092
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
b421cd5
3488082
1373f98
0897db5
604cbdc
c748f32
ffd5327
fadf03e
0f4bab2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| // Test that if we deref an immutable borrow to access a Place, | ||
| // then we can't mutate the final place. | ||
|
|
||
| #![feature(capture_disjoint_fields)] | ||
| //~^ WARNING: the feature `capture_disjoint_fields` is incomplete | ||
|
|
||
| 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.0` as mutable, as it is behind a `&` reference | ||
| z.0.0.0 = format!("X1"); | ||
| //~^ ERROR: cannot assign to `z`, as it is not declared as mutable | ||
|
||
| }; | ||
|
|
||
| c(); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes | ||
| --> $DIR/cant-mutate-imm-borrow.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[E0594]: cannot assign to `z`, as it is not declared as mutable | ||
| --> $DIR/cant-mutate-imm-borrow.rs:16:9 | ||
| | | ||
| LL | let z = (&mut y, "Z"); | ||
| | - help: consider changing this to be mutable: `mut z` | ||
| ... | ||
| LL | z.0.0.0 = format!("X1"); | ||
| | ^^^^^^^ cannot assign | ||
|
|
||
| error[E0596]: cannot borrow `z.0.0.0` as mutable, as it is behind a `&` reference | ||
| --> $DIR/cant-mutate-imm-borrow.rs:14: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.0` in closure | ||
|
|
||
| error: aborting due to 2 previous errors; 1 warning emitted | ||
|
|
||
| Some errors have detailed explanations: E0594, E0596. | ||
| For more information about an error, try `rustc --explain E0594`. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| // Test that we can't mutate a place if we need to deref an imm-borrow | ||
| // to reach it. | ||
|
|
||
| #![feature(capture_disjoint_fields)] | ||
| //~^ WARNING: the feature `capture_disjoint_fields` is incomplete | ||
|
|
||
| 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; | ||
| //~^ERROR: cannot assign to `ref_mref_x`, as it is not declared as mutable | ||
|
||
| }; | ||
|
|
||
| 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; | ||
| //~^ERROR: cannot assign to `mref_ref_x`, as it is not declared as mutable | ||
|
||
| }; | ||
|
|
||
| c(); | ||
| } | ||
|
|
||
| fn main() { | ||
| imm_mut_ref(); | ||
| mut_imm_ref(); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes | ||
| --> $DIR/mut_ref.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[E0594]: cannot assign to `ref_mref_x`, as it is not declared as mutable | ||
| --> $DIR/mut_ref.rs:15:9 | ||
| | | ||
| LL | let ref_mref_x = &mref_x; | ||
| | ---------- help: consider changing this to be mutable: `mut ref_mref_x` | ||
| ... | ||
| LL | **ref_mref_x = y; | ||
| | ^^^^^^^^^^^^ cannot assign | ||
|
|
||
| error[E0596]: cannot borrow `**ref_mref_x` as mutable, as it is behind a `&` reference | ||
| --> $DIR/mut_ref.rs:13:13 | ||
| | | ||
| LL | let ref_mref_x = &mref_x; | ||
| | ------- help: consider changing this to be a mutable reference: `&mut mref_x` | ||
| LL | | ||
| 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 | ||
|
|
||
| error[E0594]: cannot assign to `mref_ref_x`, as it is not declared as mutable | ||
| --> $DIR/mut_ref.rs:30:9 | ||
| | | ||
| LL | let mref_ref_x = &mut ref_x; | ||
| | ---------- help: consider changing this to be mutable: `mut mref_ref_x` | ||
| ... | ||
| LL | **mref_ref_x = y; | ||
| | ^^^^^^^^^^^^ cannot assign | ||
|
|
||
| error[E0596]: cannot borrow `**mref_ref_x` as mutable, as it is behind a `&` reference | ||
| --> $DIR/mut_ref.rs:28: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 4 previous errors; 1 warning emitted | ||
|
|
||
| Some errors have detailed explanations: E0594, E0596. | ||
| For more information about an error, try `rustc --explain E0594`. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| // run-pass | ||
|
|
||
| // Test that we can mutate a place through a mut-borrow | ||
| // that is captured by the closure | ||
|
|
||
| #![feature(capture_disjoint_fields)] | ||
| //~^ WARNING: the feature `capture_disjoint_fields` is incomplete | ||
|
|
||
| // Check that we can mutate when one deref is required | ||
| fn mut_ref_1() { | ||
| let mut x = String::new(); | ||
| let rx = &mut x; | ||
|
|
||
| let mut c = || { | ||
| *rx = String::new(); | ||
| }; | ||
|
|
||
| c(); | ||
| } | ||
|
|
||
| // Similar example as mut_ref_1, we don't deref the imm-borrow here, | ||
| // and so we are allowed to mutate. | ||
| fn mut_ref_2() { | ||
| let x = String::new(); | ||
| let y = String::new(); | ||
| let mut ref_x = &x; | ||
| let m_ref_x = &mut ref_x; | ||
|
|
||
| let mut c = || { | ||
| *m_ref_x = &y; | ||
| }; | ||
|
|
||
| c(); | ||
| } | ||
|
|
||
| // Check that we can mutate when multiple derefs of mut-borrows are required to reach | ||
| // the target place. | ||
| // It works because all derefs are mutable, if either of them was an immutable | ||
| // borrow, then we would not be able to deref. | ||
| fn mut_mut_ref() { | ||
| let mut x = String::new(); | ||
| let mut mref_x = &mut x; | ||
| let m_mref_x = &mut mref_x; | ||
|
|
||
| let mut c = || { | ||
| **m_mref_x = String::new(); | ||
| }; | ||
|
|
||
| c(); | ||
| } | ||
|
|
||
| fn main() { | ||
| mut_ref_1(); | ||
| mut_ref_2(); | ||
| mut_mut_ref(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes | ||
| --> $DIR/mut_ref.rs:6: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 | ||
|
|
||
| warning: 1 warning emitted | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| // run-pass | ||
|
|
||
| // Test that we can mutate a place through a mut-borrow | ||
| // that is captured by the closure | ||
| // | ||
| // More specifically we test that the if the mutable reference isn't root variable of a capture | ||
| // but rather accessed while acessing the precise capture. | ||
|
|
||
| #![feature(capture_disjoint_fields)] | ||
| //~^ WARNING: the feature `capture_disjoint_fields` is incomplete | ||
|
|
||
| fn main() { | ||
| let mut t = (10, 10); | ||
|
|
||
| let t1 = (&mut t, 10); | ||
|
|
||
| let mut c = || { | ||
| // Mutable because (*t.0) is mutable | ||
| t1.0.0 += 10; | ||
| }; | ||
|
|
||
| c(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes | ||
| --> $DIR/mut_ref_struct_mem.rs:9: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 | ||
|
|
||
| warning: 1 warning emitted | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have expected us to not try read the place
zon its own. When the feature isn't enabled we only readz.0.0.0.Debug logs from the report_mutability_error when the feature is enabled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is definitely not the error message we want-- we'd like the error to be reported on
z.0.0.0, right? I think this may be related to my comment about theused_mut_upvarsbut I'm not 100% sure.