about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Koropoff <bkoropoff@gmail.com>2014-10-04 14:04:10 -0700
committerBrian Koropoff <bkoropoff@gmail.com>2014-10-05 00:23:33 -0700
commitea3ab731a3c762829e3f2bec5bfbaa3a3a84689f (patch)
treef4b630cc34a2a7bb48989732b6991ff335f9ad44
parent20f4c45bade89f0a8df5297811af3d9f8b91d075 (diff)
downloadrust-ea3ab731a3c762829e3f2bec5bfbaa3a3a84689f.tar.gz
rust-ea3ab731a3c762829e3f2bec5bfbaa3a3a84689f.zip
Track kind of closure in upvar categorization
Keep track of the kind of closure responsible for an upvar
-rw-r--r--src/librustc/middle/borrowck/gather_loans/gather_moves.rs13
-rw-r--r--src/librustc/middle/borrowck/gather_loans/move_error.rs11
-rw-r--r--src/librustc/middle/borrowck/gather_loans/restrictions.rs2
-rw-r--r--src/librustc/middle/borrowck/mod.rs12
-rw-r--r--src/librustc/middle/mem_categorization.rs50
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs6
6 files changed, 61 insertions, 33 deletions
diff --git a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
index 1ae512a244c..cd67169ff56 100644
--- a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
+++ b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
@@ -133,16 +133,15 @@ fn check_and_get_illegal_move_origin(bccx: &BorrowckCtxt,
         mc::cat_deref(_, _, mc::BorrowedPtr(..)) |
         mc::cat_deref(_, _, mc::Implicit(..)) |
         mc::cat_deref(_, _, mc::UnsafePtr(..)) |
-        mc::cat_upvar(..) | mc::cat_static_item |
-        mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => {
+        mc::cat_upvar(..) | mc::cat_static_item => {
             Some(cmt.clone())
         }
 
-        // Can move out of captured upvars only if the destination closure
-        // type is 'once'. 1-shot stack closures emit the copied_upvar form
-        // (see mem_categorization.rs).
-        mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Once, .. }) => {
-            None
+        mc::cat_copied_upvar(mc::CopiedUpvar { kind: kind, .. }) => {
+            match kind.onceness() {
+                ast::Once => None,
+                ast::Many => Some(cmt.clone())
+            }
         }
 
         mc::cat_rvalue(..) |
diff --git a/src/librustc/middle/borrowck/gather_loans/move_error.rs b/src/librustc/middle/borrowck/gather_loans/move_error.rs
index 1b18d07f590..29677cf8971 100644
--- a/src/librustc/middle/borrowck/gather_loans/move_error.rs
+++ b/src/librustc/middle/borrowck/gather_loans/move_error.rs
@@ -115,8 +115,15 @@ fn report_cannot_move_out_of(bccx: &BorrowckCtxt, move_from: mc::cmt) {
         mc::cat_deref(_, _, mc::BorrowedPtr(..)) |
         mc::cat_deref(_, _, mc::Implicit(..)) |
         mc::cat_deref(_, _, mc::UnsafePtr(..)) |
-        mc::cat_upvar(..) | mc::cat_static_item |
-        mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => {
+        mc::cat_upvar(..) | mc::cat_static_item => {
+            bccx.span_err(
+                move_from.span,
+                format!("cannot move out of {}",
+                        bccx.cmt_to_string(&*move_from)).as_slice());
+        }
+
+        mc::cat_copied_upvar(mc::CopiedUpvar { kind: kind, .. })
+            if kind.onceness() == ast::Many => {
             bccx.span_err(
                 move_from.span,
                 format!("cannot move out of {}",
diff --git a/src/librustc/middle/borrowck/gather_loans/restrictions.rs b/src/librustc/middle/borrowck/gather_loans/restrictions.rs
index 067a73fcc9b..f30a370d068 100644
--- a/src/librustc/middle/borrowck/gather_loans/restrictions.rs
+++ b/src/librustc/middle/borrowck/gather_loans/restrictions.rs
@@ -72,7 +72,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
                 SafeIf(lp.clone(), vec![lp])
             }
 
-            mc::cat_upvar(upvar_id, _) => {
+            mc::cat_upvar(upvar_id, _, _) => {
                 // R-Variable, captured into closure
                 let lp = Rc::new(LpUpvar(upvar_id));
                 SafeIf(lp.clone(), vec![lp])
diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs
index 234afc7ae7a..710193188ee 100644
--- a/src/librustc/middle/borrowck/mod.rs
+++ b/src/librustc/middle/borrowck/mod.rs
@@ -354,8 +354,12 @@ pub fn opt_loan_path(cmt: &mc::cmt) -> Option<Rc<LoanPath>> {
 
     match cmt.cat {
         mc::cat_rvalue(..) |
-        mc::cat_static_item |
-        mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => {
+        mc::cat_static_item => {
+            None
+        }
+
+        mc::cat_copied_upvar(mc::CopiedUpvar { kind: kind, .. })
+            if kind.onceness() == ast::Many => {
             None
         }
 
@@ -363,9 +367,9 @@ pub fn opt_loan_path(cmt: &mc::cmt) -> Option<Rc<LoanPath>> {
             Some(Rc::new(LpVar(id)))
         }
 
-        mc::cat_upvar(ty::UpvarId {var_id: id, closure_expr_id: proc_id}, _) |
+        mc::cat_upvar(ty::UpvarId {var_id: id, closure_expr_id: proc_id}, _, _) |
         mc::cat_copied_upvar(mc::CopiedUpvar { upvar_id: id,
-                                               onceness: _,
+                                               kind: _,
                                                capturing_proc: proc_id }) => {
             let upvar_id = ty::UpvarId{ var_id: id, closure_expr_id: proc_id };
             Some(Rc::new(LpUpvar(upvar_id)))
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 605d3f6d6ce..207722eba00 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -83,7 +83,7 @@ pub enum categorization {
     cat_rvalue(ty::Region),            // temporary val, argument is its scope
     cat_static_item,
     cat_copied_upvar(CopiedUpvar),     // upvar copied into proc env
-    cat_upvar(ty::UpvarId, ty::UpvarBorrow), // by ref upvar from stack closure
+    cat_upvar(ty::UpvarId, ty::UpvarBorrow, Option<ty::UnboxedClosureKind>), // by ref upvar from stack or unboxed closure
     cat_local(ast::NodeId),            // local variable
     cat_deref(cmt, uint, PointerKind), // deref of a ptr
     cat_interior(cmt, InteriorKind),   // something interior: field, tuple, etc
@@ -94,9 +94,26 @@ pub enum categorization {
 }
 
 #[deriving(Clone, PartialEq)]
+pub enum CopiedUpvarKind {
+    Boxed(ast::Onceness),
+    Unboxed(ty::UnboxedClosureKind)
+}
+
+impl CopiedUpvarKind {
+    pub fn onceness(&self) -> ast::Onceness {
+        match *self {
+            Boxed(onceness) => onceness,
+            Unboxed(ty::FnUnboxedClosureKind) |
+            Unboxed(ty::FnMutUnboxedClosureKind) => ast::Many,
+            Unboxed(ty::FnOnceUnboxedClosureKind) => ast::Once
+        }
+    }
+}
+
+#[deriving(Clone, PartialEq)]
 pub struct CopiedUpvar {
     pub upvar_id: ast::NodeId,
-    pub onceness: ast::Onceness,
+    pub kind: CopiedUpvarKind,
     pub capturing_proc: ast::NodeId,
 }
 
@@ -571,14 +588,14 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
 
                       };
                       if var_is_refd {
-                          self.cat_upvar(id, span, var_id, fn_node_id)
+                          self.cat_upvar(id, span, var_id, fn_node_id, None)
                       } else {
                           Ok(Rc::new(cmt_ {
                               id:id,
                               span:span,
                               cat:cat_copied_upvar(CopiedUpvar {
                                   upvar_id: var_id,
-                                  onceness: closure_ty.onceness,
+                                  kind: Boxed(closure_ty.onceness),
                                   capturing_proc: fn_node_id,
                               }),
                               mutbl: MutabilityCategory::from_local(self.tcx(), var_id),
@@ -591,20 +608,15 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                                                  .unboxed_closures()
                                                  .borrow();
                       let kind = unboxed_closures.get(&closure_id).kind;
-                      let onceness = match kind {
-                          ty::FnUnboxedClosureKind |
-                          ty::FnMutUnboxedClosureKind => ast::Many,
-                          ty::FnOnceUnboxedClosureKind => ast::Once,
-                      };
                       if self.typer.capture_mode(fn_node_id) == ast::CaptureByRef {
-                          self.cat_upvar(id, span, var_id, fn_node_id)
+                          self.cat_upvar(id, span, var_id, fn_node_id, Some(kind))
                       } else {
                           Ok(Rc::new(cmt_ {
                               id: id,
                               span: span,
                               cat: cat_copied_upvar(CopiedUpvar {
                                   upvar_id: var_id,
-                                  onceness: onceness,
+                                  kind: Unboxed(kind),
                                   capturing_proc: fn_node_id,
                               }),
                               mutbl: MutabilityCategory::from_local(self.tcx(), var_id),
@@ -638,7 +650,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                  id: ast::NodeId,
                  span: Span,
                  var_id: ast::NodeId,
-                 fn_node_id: ast::NodeId)
+                 fn_node_id: ast::NodeId,
+                 kind: Option<ty::UnboxedClosureKind>)
                  -> McResult<cmt> {
         /*!
          * Upvars through a closure are in fact indirect
@@ -666,7 +679,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
         let base_cmt = Rc::new(cmt_ {
             id:id,
             span:span,
-            cat:cat_upvar(upvar_id, upvar_borrow),
+            cat:cat_upvar(upvar_id, upvar_borrow, kind),
             mutbl:McImmutable,
             ty:upvar_ty,
         });
@@ -1287,7 +1300,6 @@ impl cmt_ {
                 b.freely_aliasable(ctxt)
             }
 
-            cat_copied_upvar(CopiedUpvar {onceness: ast::Once, ..}) |
             cat_rvalue(..) |
             cat_local(..) |
             cat_upvar(..) |
@@ -1295,8 +1307,14 @@ impl cmt_ {
                 None
             }
 
-            cat_copied_upvar(CopiedUpvar {onceness: ast::Many, ..}) => {
-                Some(AliasableOther)
+            cat_copied_upvar(CopiedUpvar {kind: kind, capturing_proc: id, ..}) => {
+                match kind {
+                    Boxed(ast::Once) |
+                    Unboxed(ty::FnOnceUnboxedClosureKind) |
+                    Unboxed(ty::FnMutUnboxedClosureKind) => None,
+                    Boxed(_) => Some(AliasableOther),
+                    Unboxed(_) => Some(AliasableClosure(id))
+                }
             }
 
             cat_static_item(..) => {
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index 058b3ac9e6e..f533079be69 100644
--- a/src/librustc/middle/typeck/check/regionck.rs
+++ b/src/librustc/middle/typeck/check/regionck.rs
@@ -1552,7 +1552,7 @@ fn link_reborrowed_region(rcx: &Rcx,
 
     // Detect references to an upvar `x`:
     let cause = match ref_cmt.cat {
-        mc::cat_upvar(ref upvar_id, _) => {
+        mc::cat_upvar(ref upvar_id, _, _) => {
             let mut upvar_borrow_map =
                 rcx.fcx.inh.upvar_borrow_map.borrow_mut();
             match upvar_borrow_map.find_mut(upvar_id) {
@@ -1686,7 +1686,7 @@ fn adjust_upvar_borrow_kind_for_mut(rcx: &Rcx,
             mc::cat_deref(base, _, mc::BorrowedPtr(..)) |
             mc::cat_deref(base, _, mc::Implicit(..)) => {
                 match base.cat {
-                    mc::cat_upvar(ref upvar_id, _) => {
+                    mc::cat_upvar(ref upvar_id, _, _) => {
                         // if this is an implicit deref of an
                         // upvar, then we need to modify the
                         // borrow_kind of the upvar to make sure it
@@ -1739,7 +1739,7 @@ fn adjust_upvar_borrow_kind_for_unique(rcx: &Rcx, cmt: mc::cmt) {
             mc::cat_deref(base, _, mc::BorrowedPtr(..)) |
             mc::cat_deref(base, _, mc::Implicit(..)) => {
                 match base.cat {
-                    mc::cat_upvar(ref upvar_id, _) => {
+                    mc::cat_upvar(ref upvar_id, _, _) => {
                         // if this is an implicit deref of an
                         // upvar, then we need to modify the
                         // borrow_kind of the upvar to make sure it