Change the use of moved value
error to be more accurate
Previously it output `partially moved` to eagerly. This updates it to be more accurate and output `collaterally moved` for use of values that were invalidated by moves out of different fields in the same struct. Closes #15630.
This commit is contained in:
parent
35ff2def5d
commit
02c6ebde7e
@ -461,24 +461,58 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
||||
MovedInCapture => "capture",
|
||||
};
|
||||
|
||||
match the_move.kind {
|
||||
let (ol, moved_lp_msg) = match the_move.kind {
|
||||
move_data::Declared => {
|
||||
self.tcx.sess.span_err(
|
||||
use_span,
|
||||
format!("{} of possibly uninitialized variable: `{}`",
|
||||
verb,
|
||||
self.loan_path_to_string(lp)).as_slice());
|
||||
(self.loan_path_to_string(moved_lp),
|
||||
String::new())
|
||||
}
|
||||
_ => {
|
||||
let partially = if lp == moved_lp {""} else {"partially "};
|
||||
// If moved_lp is something like `x.a`, and lp is something like `x.b`, we would
|
||||
// normally generate a rather confusing message:
|
||||
//
|
||||
// error: use of moved value: `x.b`
|
||||
// note: `x.a` moved here...
|
||||
//
|
||||
// What we want to do instead is get the 'common ancestor' of the two moves and
|
||||
// use that for most of the message instead, giving is something like this:
|
||||
//
|
||||
// error: use of moved value: `x`
|
||||
// note: `x` moved here (through moving `x.a`)...
|
||||
|
||||
let common = moved_lp.common(lp);
|
||||
let has_common = common.is_some();
|
||||
let has_fork = moved_lp.has_fork(lp);
|
||||
let (nl, ol, moved_lp_msg) =
|
||||
if has_fork && has_common {
|
||||
let nl = self.loan_path_to_string(&common.unwrap());
|
||||
let ol = nl.clone();
|
||||
let moved_lp_msg = format!(" (through moving `{}`)",
|
||||
self.loan_path_to_string(moved_lp));
|
||||
(nl, ol, moved_lp_msg)
|
||||
} else {
|
||||
(self.loan_path_to_string(lp),
|
||||
self.loan_path_to_string(moved_lp),
|
||||
String::new())
|
||||
};
|
||||
|
||||
let partial = moved_lp.depth() > lp.depth();
|
||||
let msg = if !has_fork && partial { "partially " }
|
||||
else if has_fork && !has_common { "collaterally "}
|
||||
else { "" };
|
||||
self.tcx.sess.span_err(
|
||||
use_span,
|
||||
format!("{} of {}moved value: `{}`",
|
||||
verb,
|
||||
partially,
|
||||
self.loan_path_to_string(lp)).as_slice());
|
||||
msg,
|
||||
nl).as_slice());
|
||||
(ol, moved_lp_msg)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
match the_move.kind {
|
||||
move_data::Declared => {}
|
||||
@ -501,8 +535,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
||||
"moved by default (use `copy` to override)");
|
||||
self.tcx.sess.span_note(
|
||||
expr_span,
|
||||
format!("`{}` moved here because it has type `{}`, which is {}",
|
||||
self.loan_path_to_string(moved_lp),
|
||||
format!("`{}` moved here{} because it has type `{}`, which is {}",
|
||||
ol,
|
||||
moved_lp_msg,
|
||||
expr_ty.user_string(self.tcx),
|
||||
suggestion).as_slice());
|
||||
}
|
||||
@ -510,10 +545,11 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
||||
move_data::MovePat => {
|
||||
let pat_ty = ty::node_id_to_type(self.tcx, the_move.id);
|
||||
self.tcx.sess.span_note(self.tcx.map.span(the_move.id),
|
||||
format!("`{}` moved here because it has type `{}`, \
|
||||
format!("`{}` moved here{} because it has type `{}`, \
|
||||
which is moved by default (use `ref` to \
|
||||
override)",
|
||||
self.loan_path_to_string(moved_lp),
|
||||
ol,
|
||||
moved_lp_msg,
|
||||
pat_ty.user_string(self.tcx)).as_slice());
|
||||
}
|
||||
|
||||
@ -536,9 +572,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
||||
capture that instead to override)");
|
||||
self.tcx.sess.span_note(
|
||||
expr_span,
|
||||
format!("`{}` moved into closure environment here because it \
|
||||
format!("`{}` moved into closure environment here{} because it \
|
||||
has type `{}`, which is {}",
|
||||
self.loan_path_to_string(moved_lp),
|
||||
ol,
|
||||
moved_lp_msg,
|
||||
expr_ty.user_string(self.tcx),
|
||||
suggestion).as_slice());
|
||||
}
|
||||
|
@ -31,19 +31,22 @@ struct D {
|
||||
fn copy_after_move() {
|
||||
let a = box A { x: box 0, y: 1 };
|
||||
let _x = a.x;
|
||||
let _y = a.y; //~ ERROR use of partially moved
|
||||
let _y = a.y; //~ ERROR use of moved
|
||||
//~^^ NOTE `a` moved here (through moving `a.x`)
|
||||
}
|
||||
|
||||
fn move_after_move() {
|
||||
let a = box B { x: box 0, y: box 1 };
|
||||
let _x = a.x;
|
||||
let _y = a.y; //~ ERROR use of partially moved
|
||||
let _y = a.y; //~ ERROR use of moved
|
||||
//~^^ NOTE `a` moved here (through moving `a.x`)
|
||||
}
|
||||
|
||||
fn borrow_after_move() {
|
||||
let a = box A { x: box 0, y: 1 };
|
||||
let _x = a.x;
|
||||
let _y = &a.y; //~ ERROR use of partially moved
|
||||
let _y = &a.y; //~ ERROR use of moved
|
||||
//~^^ NOTE `a` moved here (through moving `a.x`)
|
||||
}
|
||||
|
||||
fn move_after_borrow() {
|
||||
@ -79,19 +82,19 @@ fn mut_borrow_after_borrow() {
|
||||
fn copy_after_move_nested() {
|
||||
let a = box C { x: box A { x: box 0, y: 1 }, y: 2 };
|
||||
let _x = a.x.x;
|
||||
let _y = a.y; //~ ERROR use of partially moved
|
||||
let _y = a.y; //~ ERROR use of collaterally moved
|
||||
}
|
||||
|
||||
fn move_after_move_nested() {
|
||||
let a = box D { x: box A { x: box 0, y: 1 }, y: box 2 };
|
||||
let _x = a.x.x;
|
||||
let _y = a.y; //~ ERROR use of partially moved
|
||||
let _y = a.y; //~ ERROR use of collaterally moved
|
||||
}
|
||||
|
||||
fn borrow_after_move_nested() {
|
||||
let a = box C { x: box A { x: box 0, y: 1 }, y: 2 };
|
||||
let _x = a.x.x;
|
||||
let _y = &a.y; //~ ERROR use of partially moved
|
||||
let _y = &a.y; //~ ERROR use of collaterally moved
|
||||
}
|
||||
|
||||
fn move_after_borrow_nested() {
|
||||
|
@ -13,13 +13,13 @@ struct A { a: int, b: Box<int> }
|
||||
fn deref_after_move() {
|
||||
let x = A { a: 1, b: box 2 };
|
||||
drop(x.b);
|
||||
drop(*x.b); //~ ERROR use of partially moved value: `*x.b`
|
||||
drop(*x.b); //~ ERROR use of moved value: `*x.b`
|
||||
}
|
||||
|
||||
fn deref_after_fu_move() {
|
||||
let x = A { a: 1, b: box 2 };
|
||||
let y = A { a: 3, .. x };
|
||||
drop(*x.b); //~ ERROR use of partially moved value: `*x.b`
|
||||
drop(*x.b); //~ ERROR use of moved value: `*x.b`
|
||||
}
|
||||
|
||||
fn borrow_after_move() {
|
||||
|
@ -13,6 +13,6 @@ extern crate debug;
|
||||
fn main() {
|
||||
let x = box 5i;
|
||||
let y = x;
|
||||
println!("{:?}", *x); //~ ERROR use of partially moved value: `*x`
|
||||
println!("{:?}", *x); //~ ERROR use of moved value: `*x`
|
||||
y.clone();
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ impl Drop for S {
|
||||
impl S {
|
||||
pub fn foo(self) -> int {
|
||||
self.bar();
|
||||
return self.x; //~ ERROR use of partially moved value: `self.x`
|
||||
return self.x; //~ ERROR use of moved value: `self.x`
|
||||
}
|
||||
|
||||
pub fn bar(self) {}
|
||||
|
@ -16,7 +16,7 @@ struct S {
|
||||
impl S {
|
||||
pub fn foo(self) -> int {
|
||||
self.bar();
|
||||
return *self.x; //~ ERROR use of partially moved value: `*self.x`
|
||||
return *self.x; //~ ERROR use of moved value: `*self.x`
|
||||
}
|
||||
|
||||
pub fn bar(self) {}
|
||||
|
Loading…
x
Reference in New Issue
Block a user