diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index b124872ba12ca..ef5edf9c6b586 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 has_downcast(&self) -> bool { + match self.kind { + LpDowncast(_, _) => true, + LpExtend(ref lp, _, LpInterior(_, _)) => { + lp.has_downcast() + } + _ => false, + } + } } // FIXME (pnkfelix): See discussion here @@ -715,16 +725,20 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { move_note)); err } else { - err.span_label(use_span, format!("value {} here after move", verb_participle)) - .span_label(move_span, format!("value moved{} here", move_note)); + err.span_label(use_span, format!("value {} here after move", verb_participle)); + 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", - self.loan_path_to_string(moved_lp), - moved_lp.ty)); + err.note(&format!( + "move occurs because {} has type `{}`, which does not implement the `Copy` trait", + if moved_lp.has_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 @@ -1391,7 +1405,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/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/compile-fail/issue-24357.rs b/src/test/compile-fail/issue-24357.rs index 5d6b989fc968a..016ce93a0bd0b 100644 --- a/src/test/compile-fail/issue-24357.rs +++ b/src/test/compile-fail/issue-24357.rs @@ -12,9 +12,9 @@ struct NoCopy; fn main() { let x = NoCopy; let f = move || { let y = x; }; - //~^ value moved (into closure) here + //~^ NOTE value moved (into closure) here 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 + //~| 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 02c09aa7d69a2..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 }; - //~^ value moved here + //~^ NOTE value moved here 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 + //~| NOTE move occurs because `x` has type `std::string::String` } fn f05() { let x = "hi".to_string(); let _y = Foo { f:(((x))) }; - //~^ value moved here + //~^ 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/borrowck/issue-41962.rs b/src/test/ui/borrowck/issue-41962.rs new file mode 100644 index 0000000000000..d592be11335e0 --- /dev/null +++ b/src/test/ui/borrowck/issue-41962.rs @@ -0,0 +1,24 @@ +// 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. +// +// 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. + +// 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: `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 new file mode 100644 index 0000000000000..50d51c4d907fd --- /dev/null +++ b/src/test/ui/borrowck/issue-41962.stderr @@ -0,0 +1,39 @@ +error[E0382]: use of partially moved value: `maybe` (Ast) + --> $DIR/issue-41962.rs:17:30 + | +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` (Ast) + --> $DIR/issue-41962.rs:17:21 + | +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[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 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 +