Skip to content

Commit

Permalink
Rollup merge of rust-lang#55696 - davidtwco:issue-55675, r=pnkfelix
Browse files Browse the repository at this point in the history
NLL Diagnostic Review 3: Missing errors for borrows of union fields

Fixes rust-lang#55675.

This PR modifies a test to make it more robust (it also fixes indentation on a doc comment, but that's not the point of the PR). See the linked issue for details.

r? @pnkfelix
  • Loading branch information
kennytm committed Nov 6, 2018
2 parents 54bc9c2 + ba09ed5 commit 1ea1a42
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 36 deletions.
20 changes: 10 additions & 10 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -506,25 +506,25 @@ pub enum BorrowKind {
/// implicit closure bindings. It is needed when the closure is
/// borrowing or mutating a mutable referent, e.g.:
///
/// let x: &mut isize = ...;
/// let y = || *x += 5;
/// let x: &mut isize = ...;
/// let y = || *x += 5;
///
/// If we were to try to translate this closure into a more explicit
/// form, we'd encounter an error with the code as written:
///
/// struct Env { x: & &mut isize }
/// let x: &mut isize = ...;
/// let y = (&mut Env { &x }, fn_ptr); // Closure is pair of env and fn
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
/// struct Env { x: & &mut isize }
/// let x: &mut isize = ...;
/// let y = (&mut Env { &x }, fn_ptr); // Closure is pair of env and fn
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
///
/// This is then illegal because you cannot mutate an `&mut` found
/// in an aliasable location. To solve, you'd have to translate with
/// an `&mut` borrow:
///
/// struct Env { x: & &mut isize }
/// let x: &mut isize = ...;
/// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
/// struct Env { x: & &mut isize }
/// let x: &mut isize = ...;
/// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
///
/// Now the assignment to `**env.x` is legal, but creating a
/// mutable pointer to `x` is not because `x` is not mutable. We
Expand Down
47 changes: 39 additions & 8 deletions src/test/ui/union/union-borrow-move-parent-sibling.nll.stderr
Original file line number Diff line number Diff line change
@@ -1,33 +1,64 @@
error[E0502]: cannot borrow `u.y` as immutable because it is also borrowed as mutable
--> $DIR/union-borrow-move-parent-sibling.rs:25:13
|
LL | let a = &mut u.x.0;
| ---------- mutable borrow occurs here
LL | let b = &u.y; //~ ERROR cannot borrow `u.y`
| ^^^^ immutable borrow occurs here
LL | use_borrow(a);
| - mutable borrow later used here

error[E0382]: use of moved value: `u`
--> $DIR/union-borrow-move-parent-sibling.rs:29:13
--> $DIR/union-borrow-move-parent-sibling.rs:32:13
|
LL | let a = u.x.0;
| ----- value moved here
LL | let a = u.y; //~ ERROR use of moved value: `u.y`
LL | let b = u.y; //~ ERROR use of moved value: `u.y`
| ^^^ value used here after move
|
= note: move occurs because `u` has type `U`, which does not implement the `Copy` trait

error[E0502]: cannot borrow `u.y` as immutable because it is also borrowed as mutable
--> $DIR/union-borrow-move-parent-sibling.rs:38:13
|
LL | let a = &mut (u.x.0).0;
| -------------- mutable borrow occurs here
LL | let b = &u.y; //~ ERROR cannot borrow `u.y`
| ^^^^ immutable borrow occurs here
LL | use_borrow(a);
| - mutable borrow later used here

error[E0382]: use of moved value: `u`
--> $DIR/union-borrow-move-parent-sibling.rs:41:13
--> $DIR/union-borrow-move-parent-sibling.rs:45:13
|
LL | let a = (u.x.0).0;
| --------- value moved here
LL | let a = u.y; //~ ERROR use of moved value: `u.y`
LL | let b = u.y; //~ ERROR use of moved value: `u.y`
| ^^^ value used here after move
|
= note: move occurs because `u` has type `U`, which does not implement the `Copy` trait

error[E0502]: cannot borrow `u.x` as immutable because it is also borrowed as mutable
--> $DIR/union-borrow-move-parent-sibling.rs:51:13
|
LL | let a = &mut *u.y;
| --------- mutable borrow occurs here
LL | let b = &u.x; //~ ERROR cannot borrow `u` (via `u.x`)
| ^^^^ immutable borrow occurs here
LL | use_borrow(a);
| - mutable borrow later used here

error[E0382]: use of moved value: `u`
--> $DIR/union-borrow-move-parent-sibling.rs:53:13
--> $DIR/union-borrow-move-parent-sibling.rs:58:13
|
LL | let a = *u.y;
| ---- value moved here
LL | let a = u.x; //~ ERROR use of moved value: `u.x`
LL | let b = u.x; //~ ERROR use of moved value: `u.x`
| ^^^ value used here after move
|
= note: move occurs because `u` has type `U`, which does not implement the `Copy` trait

error: aborting due to 3 previous errors
error: aborting due to 6 previous errors

For more information about this error, try `rustc --explain E0382`.
Some errors occurred: E0382, E0502.
For more information about an error, try `rustc --explain E0382`.
17 changes: 11 additions & 6 deletions src/test/ui/union/union-borrow-move-parent-sibling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,40 +17,45 @@ union U {
y: Box<Vec<u8>>,
}

fn use_borrow<T>(_: &T) {}

unsafe fn parent_sibling_borrow() {
let mut u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
let a = &mut u.x.0;
let a = &u.y; //~ ERROR cannot borrow `u.y`
let b = &u.y; //~ ERROR cannot borrow `u.y`
use_borrow(a);
}

unsafe fn parent_sibling_move() {
let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
let a = u.x.0;
let a = u.y; //~ ERROR use of moved value: `u.y`
let b = u.y; //~ ERROR use of moved value: `u.y`
}

unsafe fn grandparent_sibling_borrow() {
let mut u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
let a = &mut (u.x.0).0;
let a = &u.y; //~ ERROR cannot borrow `u.y`
let b = &u.y; //~ ERROR cannot borrow `u.y`
use_borrow(a);
}

unsafe fn grandparent_sibling_move() {
let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
let a = (u.x.0).0;
let a = u.y; //~ ERROR use of moved value: `u.y`
let b = u.y; //~ ERROR use of moved value: `u.y`
}

unsafe fn deref_sibling_borrow() {
let mut u = U { y: Box::default() };
let a = &mut *u.y;
let a = &u.x; //~ ERROR cannot borrow `u` (via `u.x`)
let b = &u.x; //~ ERROR cannot borrow `u` (via `u.x`)
use_borrow(a);
}

unsafe fn deref_sibling_move() {
let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
let a = *u.y;
let a = u.x; //~ ERROR use of moved value: `u.x`
let b = u.x; //~ ERROR use of moved value: `u.x`
}


Expand Down
27 changes: 15 additions & 12 deletions src/test/ui/union/union-borrow-move-parent-sibling.stderr
Original file line number Diff line number Diff line change
@@ -1,59 +1,62 @@
error[E0502]: cannot borrow `u.y` as immutable because `u.x.0` is also borrowed as mutable
--> $DIR/union-borrow-move-parent-sibling.rs:23:14
--> $DIR/union-borrow-move-parent-sibling.rs:25:14
|
LL | let a = &mut u.x.0;
| ----- mutable borrow occurs here
LL | let a = &u.y; //~ ERROR cannot borrow `u.y`
LL | let b = &u.y; //~ ERROR cannot borrow `u.y`
| ^^^ immutable borrow occurs here
LL | use_borrow(a);
LL | }
| - mutable borrow ends here

error[E0382]: use of moved value: `u.y`
--> $DIR/union-borrow-move-parent-sibling.rs:29:9
--> $DIR/union-borrow-move-parent-sibling.rs:32:9
|
LL | let a = u.x.0;
| - value moved here
LL | let a = u.y; //~ ERROR use of moved value: `u.y`
LL | let b = u.y; //~ ERROR use of moved value: `u.y`
| ^ value used here after move
|
= note: move occurs because `u.y` has type `[type error]`, which does not implement the `Copy` trait

error[E0502]: cannot borrow `u.y` as immutable because `u.x.0.0` is also borrowed as mutable
--> $DIR/union-borrow-move-parent-sibling.rs:35:14
--> $DIR/union-borrow-move-parent-sibling.rs:38:14
|
LL | let a = &mut (u.x.0).0;
| --------- mutable borrow occurs here
LL | let a = &u.y; //~ ERROR cannot borrow `u.y`
LL | let b = &u.y; //~ ERROR cannot borrow `u.y`
| ^^^ immutable borrow occurs here
LL | use_borrow(a);
LL | }
| - mutable borrow ends here

error[E0382]: use of moved value: `u.y`
--> $DIR/union-borrow-move-parent-sibling.rs:41:9
--> $DIR/union-borrow-move-parent-sibling.rs:45:9
|
LL | let a = (u.x.0).0;
| - value moved here
LL | let a = u.y; //~ ERROR use of moved value: `u.y`
LL | let b = u.y; //~ ERROR use of moved value: `u.y`
| ^ value used here after move
|
= note: move occurs because `u.y` has type `[type error]`, which does not implement the `Copy` trait

error[E0502]: cannot borrow `u` (via `u.x`) as immutable because `u` is also borrowed as mutable (via `*u.y`)
--> $DIR/union-borrow-move-parent-sibling.rs:47:14
--> $DIR/union-borrow-move-parent-sibling.rs:51:14
|
LL | let a = &mut *u.y;
| ---- mutable borrow occurs here (via `*u.y`)
LL | let a = &u.x; //~ ERROR cannot borrow `u` (via `u.x`)
LL | let b = &u.x; //~ ERROR cannot borrow `u` (via `u.x`)
| ^^^ immutable borrow occurs here (via `u.x`)
LL | use_borrow(a);
LL | }
| - mutable borrow ends here

error[E0382]: use of moved value: `u.x`
--> $DIR/union-borrow-move-parent-sibling.rs:53:9
--> $DIR/union-borrow-move-parent-sibling.rs:58:9
|
LL | let a = *u.y;
| - value moved here
LL | let a = u.x; //~ ERROR use of moved value: `u.x`
LL | let b = u.x; //~ ERROR use of moved value: `u.x`
| ^ value used here after move
|
= note: move occurs because `u.x` has type `[type error]`, which does not implement the `Copy` trait
Expand Down

0 comments on commit 1ea1a42

Please sign in to comment.