about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid Wood <david@davidtw.co>2017-12-22 15:00:26 +0000
committerDavid Wood <david@davidtw.co>2017-12-22 15:01:47 +0000
commit3dfe256b5f85a05f29a55e07d8327f5d95e12719 (patch)
tree4847902eb963b84373434460f50e1dd6527567f7
parentc428b7d9c1e771d7a7184c99fd8c6471a00ddf2e (diff)
downloadrust-3dfe256b5f85a05f29a55e07d8327f5d95e12719.tar.gz
rust-3dfe256b5f85a05f29a55e07d8327f5d95e12719.zip
Added 'move occurs because `X` is not `Copy`' note.
-rw-r--r--src/librustc_mir/borrow_check/error_reporting.rs46
1 files changed, 45 insertions, 1 deletions
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index c144962fb2d..87b8a6ae584 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<ty::Ty> {
+        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,
+                }
+            },
+        }
+    }
 }