about summary refs log tree commit diff
path: root/src/librustc_mir/transform
diff options
context:
space:
mode:
authorSantiago Pastorino <spastorino@gmail.com>2017-10-25 15:10:48 -0400
committerNiko Matsakis <niko@alum.mit.edu>2017-10-31 12:41:39 -0400
commitb8615f3bea67f12db7a84687923d62d5aabc22c1 (patch)
treed1120935ea8b3865e4909fd13084cc894fda3e92 /src/librustc_mir/transform
parentf700728a3bcb1f82b5457c4ac3051c672460ed7e (diff)
downloadrust-b8615f3bea67f12db7a84687923d62d5aabc22c1.tar.gz
rust-b8615f3bea67f12db7a84687923d62d5aabc22c1.zip
add reborrow constraints
Diffstat (limited to 'src/librustc_mir/transform')
-rw-r--r--src/librustc_mir/transform/nll/constraint_generation.rs35
1 files changed, 35 insertions, 0 deletions
diff --git a/src/librustc_mir/transform/nll/constraint_generation.rs b/src/librustc_mir/transform/nll/constraint_generation.rs
index 1acbd72a47d..1fc7dbd5bd0 100644
--- a/src/librustc_mir/transform/nll/constraint_generation.rs
+++ b/src/librustc_mir/transform/nll/constraint_generation.rs
@@ -8,9 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use rustc::hir;
 use rustc::mir::{BasicBlock, BorrowKind, Location, Lvalue, Mir, Rvalue, Statement, StatementKind};
 use rustc::mir::transform::MirSource;
 use rustc::mir::visit::Visitor;
+use rustc::mir::Lvalue::Projection;
+use rustc::mir::{LvalueProjection, ProjectionElem};
 use rustc::infer::InferCtxt;
 use rustc::traits::{self, ObligationCause};
 use rustc::ty::{self, Ty};
@@ -198,6 +201,37 @@ impl<'cx, 'gcx, 'tcx> ConstraintGeneration<'cx, 'gcx, 'tcx> {
                                    destination_region.to_region_index(),
                                    location.successor_within_block());
     }
+
+    fn add_reborrow_constraint(
+        &mut self,
+        location: Location,
+        borrow_region: ty::Region<'tcx>,
+        borrowed_lv: &Lvalue<'tcx>,
+    ) {
+        if let Projection(ref proj) = *borrowed_lv {
+            let LvalueProjection { ref base, ref elem } = **proj;
+
+            if let ProjectionElem::Deref = *elem {
+                let tcx = self.infcx.tcx;
+                let base_ty = base.ty(self.mir, tcx).to_ty(tcx);
+                let base_sty = &base_ty.sty;
+
+                if let ty::TyRef(base_region, ty::TypeAndMut{ ty: _, mutbl }) = *base_sty {
+                    match mutbl {
+                        hir::Mutability::MutImmutable => { },
+
+                        hir::Mutability::MutMutable => {
+                            self.add_reborrow_constraint(location, borrow_region, base);
+                        },
+                    }
+
+                    self.regioncx.add_outlives(base_region.to_region_index(),
+                                               borrow_region.to_region_index(),
+                                               location.successor_within_block());
+                }
+            }
+        }
+    }
 }
 
 impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cx, 'gcx, 'tcx> {
@@ -214,6 +248,7 @@ impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cx, 'gcx, 'tcx> {
         if let StatementKind::Assign(ref destination_lv, ref rv) = statement.kind {
             if let Rvalue::Ref(region, bk, ref borrowed_lv) = *rv {
                 self.add_borrow_constraint(location, destination_lv, region, bk, borrowed_lv);
+                self.add_reborrow_constraint(location, region, borrowed_lv);
             }
         }