diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index c144962fb2d88..87b8a6ae584ea 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -81,7 +81,34 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err.span_label(move_span, format!("value moved{} here", move_msg)); }; } - //FIXME: add note for closure + + if let Some(ty) = self.retrieve_type_for_place(place) { + let needs_note = match ty.sty { + ty::TypeVariants::TyClosure(id, _) => { + let tables = self.tcx.typeck_tables_of(id); + let node_id = self.tcx.hir.as_local_node_id(id).unwrap(); + let hir_id = self.tcx.hir.node_to_hir_id(node_id); + if let Some(_) = tables.closure_kind_origins().get(hir_id) { + false + } else { + true + } + }, + _ => true, + }; + + if needs_note { + let note_msg = match self.describe_place(place) { + Some(name) => format!("`{}`", name), + None => "value".to_owned(), + }; + + err.note(&format!("move occurs because {} has type `{}`, \ + which does not implement the `Copy` trait", + note_msg, ty)); + } + } + err.emit(); } } @@ -655,4 +682,21 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { fn retrieve_borrow_span(&self, borrow: &BorrowData) -> Span { self.mir.source_info(borrow.location).span } + + // Retrieve type of a place for the current MIR representation + fn retrieve_type_for_place(&self, place: &Place<'tcx>) -> Option { + match place { + Place::Local(local) => { + let local = &self.mir.local_decls[*local]; + Some(local.ty) + }, + Place::Static(ref st) => Some(st.ty), + Place::Projection(ref proj) => { + match proj.elem { + ProjectionElem::Field(_, ty) => Some(ty), + _ => None, + } + }, + } + } } diff --git a/src/test/ui/borrowck/borrowck-reinit.stderr b/src/test/ui/borrowck/borrowck-reinit.stderr index 9f08bd198223e..f36ed05051521 100644 --- a/src/test/ui/borrowck/borrowck-reinit.stderr +++ b/src/test/ui/borrowck/borrowck-reinit.stderr @@ -15,6 +15,8 @@ error[E0382]: use of moved value: `x` (Mir) | - value moved here 18 | let _ = (1,x); //~ ERROR use of moved value: `x` (Ast) | ^ value used here after move + | + = note: move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait error: aborting due to 2 previous errors diff --git a/src/test/compile-fail/moves-based-on-type-tuple.rs b/src/test/ui/moves-based-on-type-tuple.rs similarity index 77% rename from src/test/compile-fail/moves-based-on-type-tuple.rs rename to src/test/ui/moves-based-on-type-tuple.rs index a4d3e3ee02f57..27903fee117b3 100644 --- a/src/test/compile-fail/moves-based-on-type-tuple.rs +++ b/src/test/ui/moves-based-on-type-tuple.rs @@ -10,9 +10,14 @@ #![feature(box_syntax)] +// compile-flags: -Z emit-end-regions -Z borrowck=compare + fn dup(x: Box) -> Box<(Box,Box)> { - box (x, x) //~ ERROR use of moved value + box (x, x) + //~^ use of moved value: `x` (Ast) [E0382] + //~| use of moved value: `x` (Mir) [E0382] } + fn main() { dup(box 3); } diff --git a/src/test/ui/moves-based-on-type-tuple.stderr b/src/test/ui/moves-based-on-type-tuple.stderr new file mode 100644 index 0000000000000..e1667107c927c --- /dev/null +++ b/src/test/ui/moves-based-on-type-tuple.stderr @@ -0,0 +1,22 @@ +error[E0382]: use of moved value: `x` (Ast) + --> $DIR/moves-based-on-type-tuple.rs:16:13 + | +16 | box (x, x) + | - ^ value used here after move + | | + | value moved here + | + = note: move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `x` (Mir) + --> $DIR/moves-based-on-type-tuple.rs:16:13 + | +16 | box (x, x) + | - ^ value used here after move + | | + | value moved here + | + = note: move occurs because `x` has type `std::boxed::Box`, which does not implement the `Copy` trait + +error: aborting due to 2 previous errors +