Skip to content

Commit

Permalink
move_ref_pattern: change pov in diagnostics & add binding names
Browse files Browse the repository at this point in the history
  • Loading branch information
Centril committed Feb 2, 2020
1 parent 8d4973f commit bd318be
Show file tree
Hide file tree
Showing 15 changed files with 501 additions and 489 deletions.
76 changes: 44 additions & 32 deletions src/librustc_mir_build/hair/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -658,8 +658,8 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_>, pat: &Pat<'_
name,
tables.node_type(pat.hir_id),
);
sess.struct_span_err(pat.span, &format!("borrow of moved value: `{}`", name))
.span_label(binding_span, "value moved here")
sess.struct_span_err(pat.span, "borrow of moved value")
.span_label(binding_span, format!("value moved into `{}` here", name))
.span_label(binding_span, occurs_because)
.span_labels(conflicts_ref, "value borrowed here after move")
.emit();
Expand All @@ -675,50 +675,62 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_>, pat: &Pat<'_
let mut conflicts_move = Vec::new();
let mut conflicts_mut_mut = Vec::new();
let mut conflicts_mut_ref = Vec::new();
sub.each_binding(|_, hir_id, span, _| match tables.extract_binding_mode(sess, hir_id, span) {
Some(ty::BindByReference(mut_inner)) => match (mut_outer, mut_inner) {
(Mutability::Not, Mutability::Not) => {} // Both sides are `ref`.
(Mutability::Mut, Mutability::Mut) => conflicts_mut_mut.push(span), // 2x `ref mut`.
_ => conflicts_mut_ref.push(span), // `ref` + `ref mut` in either direction.
},
Some(ty::BindByValue(_)) if is_binding_by_move(cx, hir_id, span) => {
conflicts_move.push(span) // `ref mut?` + by-move conflict.
sub.each_binding(|_, hir_id, span, name| {
match tables.extract_binding_mode(sess, hir_id, span) {
Some(ty::BindByReference(mut_inner)) => match (mut_outer, mut_inner) {
(Mutability::Not, Mutability::Not) => {} // Both sides are `ref`.
(Mutability::Mut, Mutability::Mut) => conflicts_mut_mut.push((span, name)), // 2x `ref mut`.
_ => conflicts_mut_ref.push((span, name)), // `ref` + `ref mut` in either direction.
},
Some(ty::BindByValue(_)) if is_binding_by_move(cx, hir_id, span) => {
conflicts_move.push((span, name)) // `ref mut?` + by-move conflict.
}
Some(ty::BindByValue(_)) | None => {} // `ref mut?` + by-copy is fine.
}
Some(ty::BindByValue(_)) | None => {} // `ref mut?` + by-copy is fine.
});

// Report errors if any.
if !conflicts_mut_mut.is_empty() {
// Report mutability conflicts for e.g. `ref mut x @ Some(ref mut y)`.
let msg = &format!("cannot borrow `{}` as mutable more than once at a time", name);
sess.struct_span_err(pat.span, msg)
.span_label(binding_span, "first mutable borrow occurs here")
.span_labels(conflicts_mut_mut, "another mutable borrow occurs here")
.span_labels(conflicts_mut_ref, "also borrowed as immutable here")
.span_labels(conflicts_move, "also moved here")
.emit();
let mut err = sess
.struct_span_err(pat.span, "cannot borrow value as mutable more than once at a time");
err.span_label(binding_span, format!("first mutable borrow, by `{}`, occurs here", name));
for (span, name) in conflicts_mut_mut {
err.span_label(span, format!("another mutable borrow, by `{}`, occurs here", name));
}
for (span, name) in conflicts_mut_ref {
err.span_label(span, format!("also borrowed as immutable, by `{}`, here", name));
}
for (span, name) in conflicts_move {
err.span_label(span, format!("also moved into `{}` here", name));
}
err.emit();
} else if !conflicts_mut_ref.is_empty() {
// Report mutability conflicts for e.g. `ref x @ Some(ref mut y)` or the converse.
let (primary, also) = match mut_outer {
Mutability::Mut => ("mutable", "immutable"),
Mutability::Not => ("immutable", "mutable"),
};
let msg = &format!(
"cannot borrow `{}` as {} because it is also borrowed as {}",
name, also, primary,
);
sess.struct_span_err(pat.span, msg)
.span_label(binding_span, format!("{} borrow occurs here", primary))
.span_labels(conflicts_mut_ref, format!("{} borrow occurs here", also))
.span_labels(conflicts_move, "also moved here")
.emit();
let msg =
format!("cannot borrow value as {} because it is also borrowed as {}", also, primary);
let mut err = sess.struct_span_err(pat.span, &msg);
err.span_label(binding_span, format!("{} borrow, by `{}`, occurs here", primary, name));
for (span, name) in conflicts_mut_ref {
err.span_label(span, format!("{} borrow, by `{}`, occurs here", also, name));
}
for (span, name) in conflicts_move {
err.span_label(span, format!("also moved into `{}` here", name));
}
err.emit();
} else if !conflicts_move.is_empty() {
// Report by-ref and by-move conflicts, e.g. `ref x @ y`.
let msg = &format!("cannot move out of `{}` because it is borrowed", name);
sess.struct_span_err(pat.span, msg)
.span_label(binding_span, format!("borrow of `{}` occurs here", name))
.span_labels(conflicts_move, format!("move out of `{}` occurs here", name))
.emit();
let mut err =
sess.struct_span_err(pat.span, "cannot move out of value because it is borrowed");
err.span_label(binding_span, format!("value borrowed, by `{}`, here", name));
for (span, name) in conflicts_move {
err.span_label(span, format!("value moved into `{}` here", name));
}
err.emit();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ struct X {
fn main() {
let x = Some(X { x: () });
match x {
Some(ref _y @ _z) => {} //~ ERROR cannot move out of `_y` because it is borrowed
Some(ref _y @ _z) => {} //~ ERROR cannot move out of value because it is borrowed
None => panic!(),
}

Expand All @@ -26,7 +26,7 @@ fn main() {

let mut x = Some(X { x: () });
match x {
Some(ref mut _y @ _z) => {} //~ ERROR cannot move out of `_y` because it is borrowed
Some(ref mut _y @ _z) => {} //~ ERROR cannot move out of value because it is borrowed
None => panic!(),
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@
error: cannot move out of `_y` because it is borrowed
error: cannot move out of value because it is borrowed
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:15:14
|
LL | Some(ref _y @ _z) => {}
| ------^^^--
| | |
| | move out of `_y` occurs here
| borrow of `_y` occurs here
| | value moved into `_z` here
| value borrowed, by `_y`, here

error: borrow of moved value: `_z`
error: borrow of moved value
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:21:14
|
LL | Some(_z @ ref _y) => {}
| --^^^------
| | |
| | value borrowed here after move
| value moved here
| value moved into `_z` here
| move occurs because `_z` has type `X` which does implement the `Copy` trait

error: cannot move out of `_y` because it is borrowed
error: cannot move out of value because it is borrowed
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:29:14
|
LL | Some(ref mut _y @ _z) => {}
| ----------^^^--
| | |
| | move out of `_y` occurs here
| borrow of `_y` occurs here
| | value moved into `_z` here
| value borrowed, by `_y`, here

error: borrow of moved value: `_z`
error: borrow of moved value
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:35:14
|
LL | Some(_z @ ref mut _y) => {}
| --^^^----------
| | |
| | value borrowed here after move
| value moved here
| value moved into `_z` here
| move occurs because `_z` has type `X` which does implement the `Copy` trait

error[E0382]: borrow of moved value
Expand Down
16 changes: 8 additions & 8 deletions src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,37 +34,37 @@ fn main() {
a @ box b => {} //~ ERROR use of moved value
}

let ref a @ box b = Box::new(NC); //~ ERROR cannot move out of `a` because it is borrowed
let ref a @ box b = Box::new(NC); //~ ERROR cannot move out of value because it is borrowed

let ref a @ box ref mut b = Box::new(nc());
//~^ ERROR cannot borrow `a` as mutable because it is also borrowed as immutable
//~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable
let ref a @ box ref mut b = Box::new(NC);
//~^ ERROR cannot borrow `a` as mutable because it is also borrowed as immutable
//~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable
let ref a @ box ref mut b = Box::new(NC);
//~^ ERROR cannot borrow `a` as mutable because it is also borrowed as immutable
//~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable
*b = NC;
let ref a @ box ref mut b = Box::new(NC);
//~^ ERROR cannot borrow `a` as mutable because it is also borrowed as immutable
//~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable
//~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable
*b = NC;
drop(a);

let ref mut a @ box ref b = Box::new(NC);
//~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable
//~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable
//~| ERROR cannot borrow `_` as immutable because it is also borrowed as mutable
*a = Box::new(NC);
drop(b);

fn f5(ref mut a @ box ref b: Box<NC>) {
//~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable
//~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable
//~| ERROR cannot borrow `_` as immutable because it is also borrowed as mutable
*a = Box::new(NC);
drop(b);
}

match Box::new(nc()) {
ref mut a @ box ref b => {
//~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable
//~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable
//~| ERROR cannot borrow `_` as immutable because it is also borrowed as mutable
*a = Box::new(NC);
drop(b);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,74 +1,74 @@
error: cannot move out of `a` because it is borrowed
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-at-and-box.rs:37:9
|
LL | let ref a @ box b = Box::new(NC);
| -----^^^^^^^-
| | |
| | move out of `a` occurs here
| borrow of `a` occurs here
| | value moved into `b` here
| value borrowed, by `a`, here

error: cannot borrow `a` as mutable because it is also borrowed as immutable
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-at-and-box.rs:39:9
|
LL | let ref a @ box ref mut b = Box::new(nc());
| -----^^^^^^^---------
| | |
| | mutable borrow occurs here
| immutable borrow occurs here
| | mutable borrow, by `b`, occurs here
| immutable borrow, by `a`, occurs here

error: cannot borrow `a` as mutable because it is also borrowed as immutable
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-at-and-box.rs:41:9
|
LL | let ref a @ box ref mut b = Box::new(NC);
| -----^^^^^^^---------
| | |
| | mutable borrow occurs here
| immutable borrow occurs here
| | mutable borrow, by `b`, occurs here
| immutable borrow, by `a`, occurs here

error: cannot borrow `a` as mutable because it is also borrowed as immutable
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-at-and-box.rs:43:9
|
LL | let ref a @ box ref mut b = Box::new(NC);
| -----^^^^^^^---------
| | |
| | mutable borrow occurs here
| immutable borrow occurs here
| | mutable borrow, by `b`, occurs here
| immutable borrow, by `a`, occurs here

error: cannot borrow `a` as mutable because it is also borrowed as immutable
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-at-and-box.rs:46:9
|
LL | let ref a @ box ref mut b = Box::new(NC);
| -----^^^^^^^---------
| | |
| | mutable borrow occurs here
| immutable borrow occurs here
| | mutable borrow, by `b`, occurs here
| immutable borrow, by `a`, occurs here

error: cannot borrow `a` as immutable because it is also borrowed as mutable
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-at-and-box.rs:52:9
|
LL | let ref mut a @ box ref b = Box::new(NC);
| ---------^^^^^^^-----
| | |
| | immutable borrow occurs here
| mutable borrow occurs here
| | immutable borrow, by `b`, occurs here
| mutable borrow, by `a`, occurs here

error: cannot borrow `a` as immutable because it is also borrowed as mutable
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-at-and-box.rs:66:9
|
LL | ref mut a @ box ref b => {
| ---------^^^^^^^-----
| | |
| | immutable borrow occurs here
| mutable borrow occurs here
| | immutable borrow, by `b`, occurs here
| mutable borrow, by `a`, occurs here

error: cannot borrow `a` as immutable because it is also borrowed as mutable
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-at-and-box.rs:58:11
|
LL | fn f5(ref mut a @ box ref b: Box<NC>) {
| ---------^^^^^^^-----
| | |
| | immutable borrow occurs here
| mutable borrow occurs here
| | immutable borrow, by `b`, occurs here
| mutable borrow, by `a`, occurs here

error[E0382]: use of moved value
--> $DIR/borrowck-pat-at-and-box.rs:21:18
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error: borrow of moved value: `a`
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse-promotion.rs:9:9
|
LL | let a @ ref b = U;
| -^^^-----
| | |
| | value borrowed here after move
| value moved here
| value moved into `a` here
| move occurs because `a` has type `main::U` which does implement the `Copy` trait

error: aborting due to previous error
Expand Down
Loading

0 comments on commit bd318be

Please sign in to comment.