From be6734a7e719f8744c4618fe109475a626fe118e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 5 Sep 2017 23:36:34 -0700 Subject: [PATCH 1/5] Move reason for move to label --- src/librustc_borrowck/borrowck/mod.rs | 22 ++++---- src/test/compile-fail/issue-24357.rs | 5 +- ...ased-on-type-distribute-copy-over-paren.rs | 8 +-- src/test/ui/augmented-assignments.rs | 15 +++--- .../ui/borrowck/borrowck-box-insensitivity.rs | 51 +++++++++---------- src/test/ui/borrowck/issue-41962.rs | 18 +++++++ src/test/ui/borrowck/issue-41962.stderr | 16 ++++++ .../ui/moves-based-on-type-match-bindings.rs | 4 +- 8 files changed, 86 insertions(+), 53 deletions(-) create mode 100644 src/test/ui/borrowck/issue-41962.rs create mode 100644 src/test/ui/borrowck/issue-41962.stderr diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index b124872ba12ca..4b72b6987084e 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -705,28 +705,28 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { }, " (into closure)"), }; + let extra_move_label = if need_note { + format!(" because it has type `{}`, which does not implement the `Copy` trait", + moved_lp.ty) + } else { + String::new() + }; // Annotate the use and the move in the span. Watch out for // the case where the use and the move are the same. This // means the use is in a loop. err = if use_span == move_span { err.span_label( use_span, - format!("value moved{} here in previous iteration of loop", - move_note)); + format!("value moved{} here in previous iteration of loop{}", + move_note, + extra_move_label)); err } else { err.span_label(use_span, format!("value {} here after move", verb_participle)) - .span_label(move_span, format!("value moved{} here", move_note)); + .span_label(move_span, format!("value moved{} here{}", move_note, extra_move_label)); err }; - if need_note { - err.note(&format!("move occurs because `{}` has type `{}`, \ - which does not implement the `Copy` trait", - self.loan_path_to_string(moved_lp), - moved_lp.ty)); - } - // Note: we used to suggest adding a `ref binding` or calling // `clone` but those suggestions have been removed because // they are often not what you actually want to do, and were @@ -1391,7 +1391,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { LpDowncast(ref lp_base, variant_def_id) => { out.push('('); self.append_autoderefd_loan_path_to_string(&lp_base, out); - out.push(':'); + out.push_str(DOWNCAST_PRINTED_OPERATOR); out.push_str(&self.tcx.item_path_str(variant_def_id)); out.push(')'); } diff --git a/src/test/compile-fail/issue-24357.rs b/src/test/compile-fail/issue-24357.rs index 5d6b989fc968a..544679171b462 100644 --- a/src/test/compile-fail/issue-24357.rs +++ b/src/test/compile-fail/issue-24357.rs @@ -12,9 +12,8 @@ struct NoCopy; fn main() { let x = NoCopy; let f = move || { let y = x; }; - //~^ value moved (into closure) here + //~^ NOTE value moved (into closure) here because it has type `NoCopy`, which does not let z = x; //~^ ERROR use of moved value: `x` - //~| value used here after move - //~| move occurs because `x` has type `NoCopy` + //~| NOTE value used here after move } diff --git a/src/test/compile-fail/moves-based-on-type-distribute-copy-over-paren.rs b/src/test/compile-fail/moves-based-on-type-distribute-copy-over-paren.rs index 02c09aa7d69a2..0929e0b57d32d 100644 --- a/src/test/compile-fail/moves-based-on-type-distribute-copy-over-paren.rs +++ b/src/test/compile-fail/moves-based-on-type-distribute-copy-over-paren.rs @@ -17,17 +17,17 @@ fn touch(_a: &A) {} fn f00() { let x = "hi".to_string(); let _y = Foo { f:x }; - //~^ value moved here + //~^ NOTE value moved here because it has type touch(&x); //~ ERROR use of moved value: `x` - //~^ value used here after move - //~| move occurs because `x` has type `std::string::String` + //~^ NOTE value used here after move } fn f05() { let x = "hi".to_string(); let _y = Foo { f:(((x))) }; - //~^ value moved here + //~^ NOTE value moved here because it has type touch(&x); //~ ERROR use of moved value: `x` + //~^ NOTE value used here after move } fn f10() { diff --git a/src/test/ui/augmented-assignments.rs b/src/test/ui/augmented-assignments.rs index 82f5c49eeb7ae..0ac48990be4be 100644 --- a/src/test/ui/augmented-assignments.rs +++ b/src/test/ui/augmented-assignments.rs @@ -20,15 +20,18 @@ impl AddAssign for Int { fn main() { let mut x = Int(1); - x //~ error: use of moved value: `x` - //~^ value used here after move + x + //~^ error: use of moved value: `x` + //~| note: value used here after move += - x; //~ value moved here + x; + //~^ note: value moved here because it has type `Int`, which does not implement the `Copy` let y = Int(2); - //~^ consider changing this to `mut y` - y //~ error: cannot borrow immutable local variable `y` as mutable - //~| cannot borrow + //~^ note: consider changing this to `mut y` + y + //~^ error: cannot borrow immutable local variable `y` as mutable + //~| note: cannot borrow mutably += Int(1); } diff --git a/src/test/ui/borrowck/borrowck-box-insensitivity.rs b/src/test/ui/borrowck/borrowck-box-insensitivity.rs index 75bf6bce04b39..a2b2d425f1dc9 100644 --- a/src/test/ui/borrowck/borrowck-box-insensitivity.rs +++ b/src/test/ui/borrowck/borrowck-box-insensitivity.rs @@ -33,28 +33,25 @@ struct D { fn copy_after_move() { let a: Box<_> = box A { x: box 0, y: 1 }; let _x = a.x; - //~^ value moved here - let _y = a.y; //~ ERROR use of moved - //~^ move occurs because `a.x` has type `std::boxed::Box` - //~| value used here after move + //~^ NOTE value moved here because it has type `std::boxed::Box`, which does not + let _y = a.y; //~ ERROR use of moved value + //~^ NOTE value used here after move } fn move_after_move() { let a: Box<_> = box B { x: box 0, y: box 1 }; let _x = a.x; - //~^ value moved here + //~^ NOTE value moved here because it has type `std::boxed::Box`, which does not let _y = a.y; //~ ERROR use of moved - //~^ move occurs because `a.x` has type `std::boxed::Box` - //~| value used here after move + //~^ NOTE value used here after move } fn borrow_after_move() { let a: Box<_> = box A { x: box 0, y: 1 }; let _x = a.x; - //~^ value moved here + //~^ NOTE value moved here because it has type `std::boxed::Box`, which does not let _y = &a.y; //~ ERROR use of moved - //~^ move occurs because `a.x` has type `std::boxed::Box` - //~| value used here after move + //~^ NOTE value used here after move } fn move_after_borrow() { @@ -62,7 +59,7 @@ fn move_after_borrow() { let _x = &a.x; let _y = a.y; //~^ ERROR cannot move - //~| move out of + //~| NOTE move out of } fn copy_after_mut_borrow() { @@ -76,54 +73,54 @@ fn move_after_mut_borrow() { let _x = &mut a.x; let _y = a.y; //~^ ERROR cannot move - //~| move out of + //~| NOTE move out of } fn borrow_after_mut_borrow() { let mut a: Box<_> = box A { x: box 0, y: 1 }; let _x = &mut a.x; let _y = &a.y; //~ ERROR cannot borrow - //~^ immutable borrow occurs here (via `a.y`) + //~^ NOTE immutable borrow occurs here (via `a.y`) } fn mut_borrow_after_borrow() { let mut a: Box<_> = box A { x: box 0, y: 1 }; let _x = &a.x; let _y = &mut a.y; //~ ERROR cannot borrow - //~^ mutable borrow occurs here (via `a.y`) + //~^ NOTE mutable borrow occurs here (via `a.y`) } fn copy_after_move_nested() { let a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 }; let _x = a.x.x; - //~^ value moved here + //~^ NOTE value moved here because it has type `std::boxed::Box`, which does not let _y = a.y; //~ ERROR use of collaterally moved - //~| value used here after move + //~^ NOTE value used here after move } fn move_after_move_nested() { let a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 }; let _x = a.x.x; - //~^ value moved here + //~^ NOTE value moved here because it has type `std::boxed::Box`, which does not let _y = a.y; //~ ERROR use of collaterally moved - //~| value used here after move + //~^ NOTE value used here after move } fn borrow_after_move_nested() { let a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 }; let _x = a.x.x; - //~^ value moved here + //~^ NOTE value moved here because it has type `std::boxed::Box`, which does not let _y = &a.y; //~ ERROR use of collaterally moved - //~| value used here after move + //~^ NOTE value used here after move } fn move_after_borrow_nested() { let a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 }; let _x = &a.x.x; - //~^ borrow of `a.x.x` occurs here + //~^ NOTE borrow of `a.x.x` occurs here let _y = a.y; //~^ ERROR cannot move - //~| move out of + //~| NOTE move out of } fn copy_after_mut_borrow_nested() { @@ -137,23 +134,23 @@ fn move_after_mut_borrow_nested() { let _x = &mut a.x.x; let _y = a.y; //~^ ERROR cannot move - //~| move out of + //~| NOTE move out of } fn borrow_after_mut_borrow_nested() { let mut a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 }; let _x = &mut a.x.x; - //~^ mutable borrow occurs here + //~^ NOTE mutable borrow occurs here let _y = &a.y; //~ ERROR cannot borrow - //~^ immutable borrow occurs here + //~^ NOTE immutable borrow occurs here } fn mut_borrow_after_borrow_nested() { let mut a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 }; let _x = &a.x.x; - //~^ immutable borrow occurs here + //~^ NOTE immutable borrow occurs here let _y = &mut a.y; //~ ERROR cannot borrow - //~^ mutable borrow occurs here + //~^ NOTE mutable borrow occurs here } fn main() { diff --git a/src/test/ui/borrowck/issue-41962.rs b/src/test/ui/borrowck/issue-41962.rs new file mode 100644 index 0000000000000..a8e1edbdfdf1e --- /dev/null +++ b/src/test/ui/borrowck/issue-41962.rs @@ -0,0 +1,18 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn main(){ + let maybe = Some(vec![true, true]); + + loop { + if let Some(thing) = maybe { + } + } +} diff --git a/src/test/ui/borrowck/issue-41962.stderr b/src/test/ui/borrowck/issue-41962.stderr new file mode 100644 index 0000000000000..4ee11798123a9 --- /dev/null +++ b/src/test/ui/borrowck/issue-41962.stderr @@ -0,0 +1,16 @@ +error[E0382]: use of partially moved value: `maybe` + --> $DIR/issue-41962.rs:15:30 + | +15 | if let Some(thing) = maybe { + | ----- ^^^^^ value used here after move + | | + | value moved here because it has type `std::vec::Vec`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `(maybe as std::prelude::v1::Some).0` + --> $DIR/issue-41962.rs:15:21 + | +15 | if let Some(thing) = maybe { + | ^^^^^ value moved here in previous iteration of loop because it has type `std::vec::Vec`, which does not implement the `Copy` trait + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/moves-based-on-type-match-bindings.rs b/src/test/ui/moves-based-on-type-match-bindings.rs index 1fd3d03570a69..c08c1a788c1e0 100644 --- a/src/test/ui/moves-based-on-type-match-bindings.rs +++ b/src/test/ui/moves-based-on-type-match-bindings.rs @@ -21,11 +21,11 @@ fn f10() { let y = match x { Foo {f} => {} + //~^ NOTE value moved here because it has type `std::string::String`, which does not }; touch(&x); //~ ERROR use of partially moved value: `x` - //~^ value used here after move - //~| move occurs because `x.f` has type `std::string::String` + //~^ NOTE value used here after move } fn main() {} From 6c506d4c71f957fa5ca50d364c7f56daa0872064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 1 Jan 2018 22:10:04 -0800 Subject: [PATCH 2/5] Address review comments: make label shorter --- src/librustc_borrowck/borrowck/mod.rs | 22 ++++++++++++++-------- src/test/ui/borrowck/issue-41962.stderr | 3 ++- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 4b72b6987084e..b33cd19b7a9f1 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -705,12 +705,6 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { }, " (into closure)"), }; - let extra_move_label = if need_note { - format!(" because it has type `{}`, which does not implement the `Copy` trait", - moved_lp.ty) - } else { - String::new() - }; // Annotate the use and the move in the span. Watch out for // the case where the use and the move are the same. This // means the use is in a loop. @@ -720,10 +714,22 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { format!("value moved{} here in previous iteration of loop{}", move_note, extra_move_label)); + + if need_note { + err.note(&format!("value moved because it has type `{}`, \ + which does not implement the `Copy` trait", + moved_lp.ty) + } err } else { - err.span_label(use_span, format!("value {} here after move", verb_participle)) - .span_label(move_span, format!("value moved{} here{}", move_note, extra_move_label)); + err.span_label(use_span, format!("value {} here after move", verb_participle)); + let extra_move_label = if need_note { + &format!(" because it has type `{}`, which does not implement the `Copy` trait", + moved_lp.ty) + } else { + "" + }; + err.span_label(move_span,format!("value moved{} here{}", move_note, extra_move_label)); err }; diff --git a/src/test/ui/borrowck/issue-41962.stderr b/src/test/ui/borrowck/issue-41962.stderr index 4ee11798123a9..caa67835ee573 100644 --- a/src/test/ui/borrowck/issue-41962.stderr +++ b/src/test/ui/borrowck/issue-41962.stderr @@ -10,7 +10,8 @@ error[E0382]: use of moved value: `(maybe as std::prelude::v1::Some).0` --> $DIR/issue-41962.rs:15:21 | 15 | if let Some(thing) = maybe { - | ^^^^^ value moved here in previous iteration of loop because it has type `std::vec::Vec`, which does not implement the `Copy` trait + | ^^^^^ value moved here in previous iteration of loop + = note: value moved because it has type `std::vec::Vec`, which does not implement the `Copy` trait error: aborting due to 2 previous errors From 48b684a40a503a85f5e62f03ea7217d40fee6e1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 1 Jan 2018 22:23:13 -0800 Subject: [PATCH 3/5] Be ambiguous when type cannot be properly mentioned --- src/librustc_borrowck/borrowck/mod.rs | 40 +++++++++------ src/test/compile-fail/issue-24357.rs | 3 +- ...ased-on-type-distribute-copy-over-paren.rs | 6 ++- src/test/ui/augmented-assignments.rs | 15 +++--- .../ui/borrowck/borrowck-box-insensitivity.rs | 51 ++++++++++--------- src/test/ui/borrowck/issue-41962.rs | 2 + src/test/ui/borrowck/issue-41962.stderr | 7 ++- .../ui/moves-based-on-type-match-bindings.rs | 4 +- 8 files changed, 72 insertions(+), 56 deletions(-) diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index b33cd19b7a9f1..99403d012394f 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -346,6 +346,16 @@ impl<'tcx> LoanPath<'tcx> { } fn to_type(&self) -> Ty<'tcx> { self.ty } + + fn is_downcast(&self) -> bool { + match self.kind { + LpDowncast(_, _) => true, + LpExtend(ref lp, _, LpInterior(_, _)) => { + lp.is_downcast() + } + _ => false, + } + } } // FIXME (pnkfelix): See discussion here @@ -711,28 +721,26 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { err = if use_span == move_span { err.span_label( use_span, - format!("value moved{} here in previous iteration of loop{}", - move_note, - extra_move_label)); - - if need_note { - err.note(&format!("value moved because it has type `{}`, \ - which does not implement the `Copy` trait", - moved_lp.ty) - } + format!("value moved{} here in previous iteration of loop", + move_note)); err } else { err.span_label(use_span, format!("value {} here after move", verb_participle)); - let extra_move_label = if need_note { - &format!(" because it has type `{}`, which does not implement the `Copy` trait", - moved_lp.ty) - } else { - "" - }; - err.span_label(move_span,format!("value moved{} here{}", move_note, extra_move_label)); + err.span_label(move_span, format!("value moved{} here", move_note)); err }; + if need_note { + err.note(&format!( + "move occurs because {} has type `{}`, which does not implement the `Copy` trait", + if moved_lp.is_downcast() { + "the value".to_string() + } else { + format!("`{}`", self.loan_path_to_string(moved_lp)) + }, + moved_lp.ty)); + } + // Note: we used to suggest adding a `ref binding` or calling // `clone` but those suggestions have been removed because // they are often not what you actually want to do, and were diff --git a/src/test/compile-fail/issue-24357.rs b/src/test/compile-fail/issue-24357.rs index 544679171b462..016ce93a0bd0b 100644 --- a/src/test/compile-fail/issue-24357.rs +++ b/src/test/compile-fail/issue-24357.rs @@ -12,8 +12,9 @@ struct NoCopy; fn main() { let x = NoCopy; let f = move || { let y = x; }; - //~^ NOTE value moved (into closure) here because it has type `NoCopy`, which does not + //~^ NOTE value moved (into closure) here let z = x; //~^ ERROR use of moved value: `x` //~| NOTE value used here after move + //~| NOTE move occurs because `x` has type `NoCopy` } diff --git a/src/test/compile-fail/moves-based-on-type-distribute-copy-over-paren.rs b/src/test/compile-fail/moves-based-on-type-distribute-copy-over-paren.rs index 0929e0b57d32d..5329dcaaaf4a2 100644 --- a/src/test/compile-fail/moves-based-on-type-distribute-copy-over-paren.rs +++ b/src/test/compile-fail/moves-based-on-type-distribute-copy-over-paren.rs @@ -17,17 +17,19 @@ fn touch(_a: &A) {} fn f00() { let x = "hi".to_string(); let _y = Foo { f:x }; - //~^ NOTE value moved here because it has type + //~^ NOTE value moved here touch(&x); //~ ERROR use of moved value: `x` //~^ NOTE value used here after move + //~| NOTE move occurs because `x` has type `std::string::String` } fn f05() { let x = "hi".to_string(); let _y = Foo { f:(((x))) }; - //~^ NOTE value moved here because it has type + //~^ NOTE value moved here touch(&x); //~ ERROR use of moved value: `x` //~^ NOTE value used here after move + //~| NOTE move occurs because `x` has type `std::string::String` } fn f10() { diff --git a/src/test/ui/augmented-assignments.rs b/src/test/ui/augmented-assignments.rs index 0ac48990be4be..82f5c49eeb7ae 100644 --- a/src/test/ui/augmented-assignments.rs +++ b/src/test/ui/augmented-assignments.rs @@ -20,18 +20,15 @@ impl AddAssign for Int { fn main() { let mut x = Int(1); - x - //~^ error: use of moved value: `x` - //~| note: value used here after move + x //~ error: use of moved value: `x` + //~^ value used here after move += - x; - //~^ note: value moved here because it has type `Int`, which does not implement the `Copy` + x; //~ value moved here let y = Int(2); - //~^ note: consider changing this to `mut y` - y - //~^ error: cannot borrow immutable local variable `y` as mutable - //~| note: cannot borrow mutably + //~^ consider changing this to `mut y` + y //~ error: cannot borrow immutable local variable `y` as mutable + //~| cannot borrow += Int(1); } diff --git a/src/test/ui/borrowck/borrowck-box-insensitivity.rs b/src/test/ui/borrowck/borrowck-box-insensitivity.rs index a2b2d425f1dc9..75bf6bce04b39 100644 --- a/src/test/ui/borrowck/borrowck-box-insensitivity.rs +++ b/src/test/ui/borrowck/borrowck-box-insensitivity.rs @@ -33,25 +33,28 @@ struct D { fn copy_after_move() { let a: Box<_> = box A { x: box 0, y: 1 }; let _x = a.x; - //~^ NOTE value moved here because it has type `std::boxed::Box`, which does not - let _y = a.y; //~ ERROR use of moved value - //~^ NOTE value used here after move + //~^ value moved here + let _y = a.y; //~ ERROR use of moved + //~^ move occurs because `a.x` has type `std::boxed::Box` + //~| value used here after move } fn move_after_move() { let a: Box<_> = box B { x: box 0, y: box 1 }; let _x = a.x; - //~^ NOTE value moved here because it has type `std::boxed::Box`, which does not + //~^ value moved here let _y = a.y; //~ ERROR use of moved - //~^ NOTE value used here after move + //~^ move occurs because `a.x` has type `std::boxed::Box` + //~| value used here after move } fn borrow_after_move() { let a: Box<_> = box A { x: box 0, y: 1 }; let _x = a.x; - //~^ NOTE value moved here because it has type `std::boxed::Box`, which does not + //~^ value moved here let _y = &a.y; //~ ERROR use of moved - //~^ NOTE value used here after move + //~^ move occurs because `a.x` has type `std::boxed::Box` + //~| value used here after move } fn move_after_borrow() { @@ -59,7 +62,7 @@ fn move_after_borrow() { let _x = &a.x; let _y = a.y; //~^ ERROR cannot move - //~| NOTE move out of + //~| move out of } fn copy_after_mut_borrow() { @@ -73,54 +76,54 @@ fn move_after_mut_borrow() { let _x = &mut a.x; let _y = a.y; //~^ ERROR cannot move - //~| NOTE move out of + //~| move out of } fn borrow_after_mut_borrow() { let mut a: Box<_> = box A { x: box 0, y: 1 }; let _x = &mut a.x; let _y = &a.y; //~ ERROR cannot borrow - //~^ NOTE immutable borrow occurs here (via `a.y`) + //~^ immutable borrow occurs here (via `a.y`) } fn mut_borrow_after_borrow() { let mut a: Box<_> = box A { x: box 0, y: 1 }; let _x = &a.x; let _y = &mut a.y; //~ ERROR cannot borrow - //~^ NOTE mutable borrow occurs here (via `a.y`) + //~^ mutable borrow occurs here (via `a.y`) } fn copy_after_move_nested() { let a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 }; let _x = a.x.x; - //~^ NOTE value moved here because it has type `std::boxed::Box`, which does not + //~^ value moved here let _y = a.y; //~ ERROR use of collaterally moved - //~^ NOTE value used here after move + //~| value used here after move } fn move_after_move_nested() { let a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 }; let _x = a.x.x; - //~^ NOTE value moved here because it has type `std::boxed::Box`, which does not + //~^ value moved here let _y = a.y; //~ ERROR use of collaterally moved - //~^ NOTE value used here after move + //~| value used here after move } fn borrow_after_move_nested() { let a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 }; let _x = a.x.x; - //~^ NOTE value moved here because it has type `std::boxed::Box`, which does not + //~^ value moved here let _y = &a.y; //~ ERROR use of collaterally moved - //~^ NOTE value used here after move + //~| value used here after move } fn move_after_borrow_nested() { let a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 }; let _x = &a.x.x; - //~^ NOTE borrow of `a.x.x` occurs here + //~^ borrow of `a.x.x` occurs here let _y = a.y; //~^ ERROR cannot move - //~| NOTE move out of + //~| move out of } fn copy_after_mut_borrow_nested() { @@ -134,23 +137,23 @@ fn move_after_mut_borrow_nested() { let _x = &mut a.x.x; let _y = a.y; //~^ ERROR cannot move - //~| NOTE move out of + //~| move out of } fn borrow_after_mut_borrow_nested() { let mut a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 }; let _x = &mut a.x.x; - //~^ NOTE mutable borrow occurs here + //~^ mutable borrow occurs here let _y = &a.y; //~ ERROR cannot borrow - //~^ NOTE immutable borrow occurs here + //~^ immutable borrow occurs here } fn mut_borrow_after_borrow_nested() { let mut a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 }; let _x = &a.x.x; - //~^ NOTE immutable borrow occurs here + //~^ immutable borrow occurs here let _y = &mut a.y; //~ ERROR cannot borrow - //~^ NOTE mutable borrow occurs here + //~^ mutable borrow occurs here } fn main() { diff --git a/src/test/ui/borrowck/issue-41962.rs b/src/test/ui/borrowck/issue-41962.rs index a8e1edbdfdf1e..d8a4436532a0d 100644 --- a/src/test/ui/borrowck/issue-41962.rs +++ b/src/test/ui/borrowck/issue-41962.rs @@ -13,6 +13,8 @@ pub fn main(){ loop { if let Some(thing) = maybe { + //~^ ERROR use of partially moved value + //~| ERROR use of moved value } } } diff --git a/src/test/ui/borrowck/issue-41962.stderr b/src/test/ui/borrowck/issue-41962.stderr index caa67835ee573..51e4409c81f80 100644 --- a/src/test/ui/borrowck/issue-41962.stderr +++ b/src/test/ui/borrowck/issue-41962.stderr @@ -4,14 +4,17 @@ error[E0382]: use of partially moved value: `maybe` 15 | if let Some(thing) = maybe { | ----- ^^^^^ value used here after move | | - | value moved here because it has type `std::vec::Vec`, which does not implement the `Copy` trait + | value moved here + | + = note: move occurs because the value has type `std::vec::Vec`, which does not implement the `Copy` trait error[E0382]: use of moved value: `(maybe as std::prelude::v1::Some).0` --> $DIR/issue-41962.rs:15:21 | 15 | if let Some(thing) = maybe { | ^^^^^ value moved here in previous iteration of loop - = note: value moved because it has type `std::vec::Vec`, which does not implement the `Copy` trait + | + = note: move occurs because the value has type `std::vec::Vec`, which does not implement the `Copy` trait error: aborting due to 2 previous errors diff --git a/src/test/ui/moves-based-on-type-match-bindings.rs b/src/test/ui/moves-based-on-type-match-bindings.rs index c08c1a788c1e0..1fd3d03570a69 100644 --- a/src/test/ui/moves-based-on-type-match-bindings.rs +++ b/src/test/ui/moves-based-on-type-match-bindings.rs @@ -21,11 +21,11 @@ fn f10() { let y = match x { Foo {f} => {} - //~^ NOTE value moved here because it has type `std::string::String`, which does not }; touch(&x); //~ ERROR use of partially moved value: `x` - //~^ NOTE value used here after move + //~^ value used here after move + //~| move occurs because `x.f` has type `std::string::String` } fn main() {} From e027f5a99e16d2509478c71856e0246e11148322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 3 Jan 2018 13:55:40 -0800 Subject: [PATCH 4/5] Add mir test, review comments --- src/librustc_borrowck/borrowck/mod.rs | 6 ++--- src/test/ui/borrowck/issue-41962.rs | 10 ++++--- src/test/ui/borrowck/issue-41962.stderr | 36 ++++++++++++++++++++----- 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 99403d012394f..ef5edf9c6b586 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -347,11 +347,11 @@ impl<'tcx> LoanPath<'tcx> { fn to_type(&self) -> Ty<'tcx> { self.ty } - fn is_downcast(&self) -> bool { + fn has_downcast(&self) -> bool { match self.kind { LpDowncast(_, _) => true, LpExtend(ref lp, _, LpInterior(_, _)) => { - lp.is_downcast() + lp.has_downcast() } _ => false, } @@ -733,7 +733,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { if need_note { err.note(&format!( "move occurs because {} has type `{}`, which does not implement the `Copy` trait", - if moved_lp.is_downcast() { + if moved_lp.has_downcast() { "the value".to_string() } else { format!("`{}`", self.loan_path_to_string(moved_lp)) diff --git a/src/test/ui/borrowck/issue-41962.rs b/src/test/ui/borrowck/issue-41962.rs index d8a4436532a0d..d592be11335e0 100644 --- a/src/test/ui/borrowck/issue-41962.rs +++ b/src/test/ui/borrowck/issue-41962.rs @@ -1,4 +1,4 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,13 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -Z borrowck=compare + pub fn main(){ let maybe = Some(vec![true, true]); loop { if let Some(thing) = maybe { - //~^ ERROR use of partially moved value - //~| ERROR use of moved value + //~^ ERROR use of partially moved value: `maybe` (Ast) [E0382] + //~| ERROR use of moved value: `(maybe as std::prelude::v1::Some).0` (Ast) [E0382] + //~| ERROR use of moved value: `maybe` (Mir) [E0382] + //~| ERROR use of moved value: `maybe.0` (Mir) [E0382] } } } diff --git a/src/test/ui/borrowck/issue-41962.stderr b/src/test/ui/borrowck/issue-41962.stderr index 51e4409c81f80..4522029593fa1 100644 --- a/src/test/ui/borrowck/issue-41962.stderr +++ b/src/test/ui/borrowck/issue-41962.stderr @@ -1,20 +1,42 @@ -error[E0382]: use of partially moved value: `maybe` - --> $DIR/issue-41962.rs:15:30 +error[E0382]: use of partially moved value: `maybe` (Ast) + --> $DIR/issue-41962.rs:17:30 | -15 | if let Some(thing) = maybe { +17 | if let Some(thing) = maybe { | ----- ^^^^^ value used here after move | | | value moved here | = note: move occurs because the value has type `std::vec::Vec`, which does not implement the `Copy` trait -error[E0382]: use of moved value: `(maybe as std::prelude::v1::Some).0` - --> $DIR/issue-41962.rs:15:21 +error[E0382]: use of moved value: `(maybe as std::prelude::v1::Some).0` (Ast) + --> $DIR/issue-41962.rs:17:21 | -15 | if let Some(thing) = maybe { +17 | if let Some(thing) = maybe { | ^^^^^ value moved here in previous iteration of loop | = note: move occurs because the value has type `std::vec::Vec`, which does not implement the `Copy` trait -error: aborting due to 2 previous errors +error[E0382]: use of moved value: `maybe` (Mir) + --> $DIR/issue-41962.rs:17:16 + | +17 | if let Some(thing) = maybe { + | ^^^^^-----^ + | | | + | | value moved here + | value used here after move + | + = note: move occurs because `maybe` has type `std::option::Option>`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `maybe.0` (Mir) + --> $DIR/issue-41962.rs:17:21 + | +17 | if let Some(thing) = maybe { + | ^^^^^ + | | + | value used here after move + | value moved here in previous iteration of loop + | + = note: move occurs because `maybe.0` has type `std::vec::Vec`, which does not implement the `Copy` trait + +error: aborting due to 4 previous errors From a4d46b3d87e9c83ffb78489a513a100e5422ac81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 3 Jan 2018 14:13:32 -0800 Subject: [PATCH 5/5] Tweak to mir borrow in a loop diagnostic --- .../borrow_check/error_reporting.rs | 18 +++++++++++------- src/test/ui/borrowck/issue-41962.stderr | 5 +---- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 1d9e05f677439..19bebea7cb8f1 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -62,13 +62,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Origin::Mir, ); - err.span_label( - span, - format!( - "value {} here after move", - desired_action.as_verb_in_past_tense() - ), - ); + let mut is_loop_move = false; for moi in mois { let move_msg = ""; //FIXME: add " (into closure)" let move_span = self.mir.source_info(self.move_data.moves[*moi].source).span; @@ -77,10 +71,20 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { span, format!("value moved{} here in previous iteration of loop", move_msg), ); + is_loop_move = true; } else { err.span_label(move_span, format!("value moved{} here", move_msg)); }; } + if !is_loop_move { + err.span_label( + span, + format!( + "value {} here after move", + desired_action.as_verb_in_past_tense() + ), + ); + } if let Some(ty) = self.retrieve_type_for_place(place) { let needs_note = match ty.sty { diff --git a/src/test/ui/borrowck/issue-41962.stderr b/src/test/ui/borrowck/issue-41962.stderr index 4522029593fa1..50d51c4d907fd 100644 --- a/src/test/ui/borrowck/issue-41962.stderr +++ b/src/test/ui/borrowck/issue-41962.stderr @@ -31,10 +31,7 @@ error[E0382]: use of moved value: `maybe.0` (Mir) --> $DIR/issue-41962.rs:17:21 | 17 | if let Some(thing) = maybe { - | ^^^^^ - | | - | value used here after move - | value moved here in previous iteration of loop + | ^^^^^ value moved here in previous iteration of loop | = note: move occurs because `maybe.0` has type `std::vec::Vec`, which does not implement the `Copy` trait