]> git.lizzy.rs Git - rust.git/commitdiff
Explain why closure is moved in error message
authorTommy Ip <hkmp7tommy@gmail.com>
Sun, 28 May 2017 21:08:51 +0000 (22:08 +0100)
committerTommy Ip <hkmp7tommy@gmail.com>
Tue, 30 May 2017 10:05:16 +0000 (11:05 +0100)
src/librustc/ty/context.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_typeck/check/upvar.rs

index bc9fd1147b6ea8bc5a0cd9af2b8331e1391c5d64..8deeb35270d259a10ef6bbb0c9a8e94217e58050 100644 (file)
@@ -230,9 +230,9 @@ pub struct TypeckTables<'tcx> {
     /// Records the type of each closure.
     pub closure_tys: NodeMap<ty::PolyFnSig<'tcx>>,
 
-    /// Records the kind of each closure and the span of the variable that
-    /// cause the closure to be this kind.
-    pub closure_kinds: NodeMap<(ty::ClosureKind, Option<Span>)>,
+    /// Records the kind of each closure and the span and name of the variable
+    /// that caused the closure to be this kind.
+    pub closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>,
 
     /// For each fn, records the "liberated" types of its arguments
     /// and return type. Liberated means that all bound regions
index 297df4978a59e8a567c5bcdcac076fbf25d4485c..b25252eef8c68d23a4c23909c1cb9c569ae08c98 100644 (file)
@@ -39,8 +39,6 @@
 use rustc::ty::{self, TyCtxt};
 use rustc::ty::maps::Providers;
 
-use syntax_pos::DUMMY_SP;
-
 use std::fmt;
 use std::rc::Rc;
 use std::hash::{Hash, Hasher};
@@ -594,12 +592,14 @@ pub fn report_use_of_moved_value(&self,
                     verb, msg, nl);
                 let need_note = match lp.ty.sty {
                     ty::TypeVariants::TyClosure(id, _) => {
-                        if let Ok(ty::ClosureKind::FnOnce) =
-                           ty::queries::closure_kind::try_get(self.tcx, DUMMY_SP, id) {
-                            err.help("closure was moved because it only implements `FnOnce`");
-                            if let Some(&(_kind, Some(span))) = self.tables.closure_kinds.get( ) {
-                                err.span_label(span, "move occured here");
-                            }
+                        let node_id = self.tcx.hir.as_local_node_id(id).unwrap();
+                        if let Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) =
+                            self.tables.closure_kinds.get(&node_id)
+                        {
+                            err.help(&format!("closure cannot be invoked more than once because \
+                                              it moves the variable `{}` out of its environment",
+                                              name));
+                            err.span_label(span, format!("{} moved here", name));
                             false
                         } else {
                             true
index 3d5cb13b0eed57eebac1ed3e3713361f6b3fa734..114290c52d195469dc23d6fe2b92d29ce182caab 100644 (file)
@@ -74,7 +74,7 @@ pub fn closure_analyze(&self, body: &'gcx hir::Body) {
 
 struct SeedBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
-    temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<Span>)>,
+    temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>,
 }
 
 impl<'a, 'gcx, 'tcx> Visitor<'gcx> for SeedBorrowKind<'a, 'gcx, 'tcx> {
@@ -143,12 +143,12 @@ fn check_closure(&mut self,
 
 struct AdjustBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
-    temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<Span>)>,
+    temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>,
 }
 
 impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
     fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
-           temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<Span>)>)
+           temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>)
            -> AdjustBorrowKind<'a, 'gcx, 'tcx> {
         AdjustBorrowKind { fcx: fcx, temp_closure_kinds: temp_closure_kinds }
     }
@@ -211,8 +211,8 @@ fn analyze_closure(&mut self,
 
         // If we are also inferred the closure kind here, update the
         // main table and process any deferred resolutions.
-        if let Some(&(kind, span)) = self.temp_closure_kinds.get(&id) {
-            self.fcx.tables.borrow_mut().closure_kinds.insert(id, (kind, span));
+        if let Some(&(kind, context)) = self.temp_closure_kinds.get(&id) {
+            self.fcx.tables.borrow_mut().closure_kinds.insert(id, (kind, context));
             let closure_def_id = self.fcx.tcx.hir.local_def_id(id);
             debug!("closure_kind({:?}) = {:?}", closure_def_id, kind);
 
@@ -272,11 +272,12 @@ fn adjust_upvar_borrow_kind_for_consume(&mut self,
             euv::Move(_) => { }
         }
 
+        let tcx = self.fcx.tcx;
+
         // watch out for a move of the deref of a borrowed pointer;
         // for that to be legal, the upvar would have to be borrowed
         // by value instead
         let guarantor = cmt.guarantor();
-        let tcx = self.fcx.tcx;
         debug!("adjust_upvar_borrow_kind_for_consume: guarantor={:?}",
                guarantor);
         match guarantor.cat {
@@ -291,7 +292,8 @@ fn adjust_upvar_borrow_kind_for_consume(&mut self,
                         // to move out of an upvar, this must be a FnOnce closure
                         self.adjust_closure_kind(upvar_id.closure_expr_id,
                                                  ty::ClosureKind::FnOnce,
-                                                 tcx.hir.span(upvar_id.var_id));
+                                                 guarantor.span,
+                                                 tcx.hir.name(upvar_id.var_id));
 
                         let upvar_capture_map =
                             &mut self.fcx.tables.borrow_mut().upvar_capture_map;
@@ -306,7 +308,8 @@ fn adjust_upvar_borrow_kind_for_consume(&mut self,
                         // of the environment.
                         self.adjust_closure_kind(upvar_id.closure_expr_id,
                                                  ty::ClosureKind::FnOnce,
-                                                 tcx.hir.span(upvar_id.var_id));
+                                                 guarantor.span,
+                                                 tcx.hir.name(upvar_id.var_id));
                     }
                     mc::NoteNone => {
                     }
@@ -334,7 +337,7 @@ fn adjust_upvar_borrow_kind_for_mut(&mut self, cmt: mc::cmt<'tcx>) {
 
             Categorization::Deref(base, _, mc::BorrowedPtr(..)) |
             Categorization::Deref(base, _, mc::Implicit(..)) => {
-                if !self.try_adjust_upvar_deref(&cmt.note, ty::MutBorrow) {
+                if !self.try_adjust_upvar_deref(cmt, ty::MutBorrow) {
                     // assignment to deref of an `&mut`
                     // borrowed pointer implies that the
                     // pointer itself must be unique, but not
@@ -368,7 +371,7 @@ fn adjust_upvar_borrow_kind_for_unique(&mut self, cmt: mc::cmt<'tcx>) {
 
             Categorization::Deref(base, _, mc::BorrowedPtr(..)) |
             Categorization::Deref(base, _, mc::Implicit(..)) => {
-                if !self.try_adjust_upvar_deref(&cmt.note, ty::UniqueImmBorrow) {
+                if !self.try_adjust_upvar_deref(cmt, ty::UniqueImmBorrow) {
                     // for a borrowed pointer to be unique, its
                     // base must be unique
                     self.adjust_upvar_borrow_kind_for_unique(base);
@@ -385,7 +388,7 @@ fn adjust_upvar_borrow_kind_for_unique(&mut self, cmt: mc::cmt<'tcx>) {
     }
 
     fn try_adjust_upvar_deref(&mut self,
-                              note: &mc::Note,
+                              cmt: mc::cmt<'tcx>,
                               borrow_kind: ty::BorrowKind)
                               -> bool
     {
@@ -399,7 +402,7 @@ fn try_adjust_upvar_deref(&mut self,
 
         let tcx = self.fcx.tcx;
 
-        match *note {
+        match cmt.note {
             mc::NoteUpvarRef(upvar_id) => {
                 // if this is an implicit deref of an
                 // upvar, then we need to modify the
@@ -414,7 +417,8 @@ fn try_adjust_upvar_deref(&mut self,
                 // also need to be in an FnMut closure since this is not an ImmBorrow
                 self.adjust_closure_kind(upvar_id.closure_expr_id,
                                          ty::ClosureKind::FnMut,
-                                         tcx.hir.span(upvar_id.var_id));
+                                         cmt.span,
+                                         tcx.hir.name(upvar_id.var_id));
 
                 true
             }
@@ -424,7 +428,8 @@ fn try_adjust_upvar_deref(&mut self,
                 // upvar, we need to be an FnMut closure
                 self.adjust_closure_kind(upvar_id.closure_expr_id,
                                          ty::ClosureKind::FnMut,
-                                         tcx.hir.span(upvar_id.var_id));
+                                         cmt.span,
+                                         tcx.hir.name(upvar_id.var_id));
 
                 true
             }
@@ -472,9 +477,10 @@ fn adjust_upvar_borrow_kind(&mut self,
     fn adjust_closure_kind(&mut self,
                            closure_id: ast::NodeId,
                            new_kind: ty::ClosureKind,
-                           upvar_span: Span) {
-        debug!("adjust_closure_kind(closure_id={}, new_kind={:?})",
-               closure_id, new_kind);
+                           upvar_span: Span,
+                           var_name: ast::Name) {
+        debug!("adjust_closure_kind(closure_id={}, new_kind={:?}, upvar_span={:?}, var_name={})",
+               closure_id, new_kind, upvar_span, var_name);
 
         if let Some(&(existing_kind, _)) = self.temp_closure_kinds.get(&closure_id) {
             debug!("adjust_closure_kind: closure_id={}, existing_kind={:?}, new_kind={:?}",
@@ -492,7 +498,10 @@ fn adjust_closure_kind(&mut self,
                 (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
                 (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
                     // new kind is stronger than the old kind
-                    self.temp_closure_kinds.insert(closure_id, (new_kind, Some(upvar_span)));
+                    self.temp_closure_kinds.insert(
+                        closure_id,
+                        (new_kind, Some((upvar_span, var_name)))
+                    );
                 }
             }
         }