about summary refs log tree commit diff
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
parentf700728a3bcb1f82b5457c4ac3051c672460ed7e (diff)
downloadrust-b8615f3bea67f12db7a84687923d62d5aabc22c1.tar.gz
rust-b8615f3bea67f12db7a84687923d62d5aabc22c1.zip
add reborrow constraints
-rw-r--r--src/librustc_mir/transform/nll/constraint_generation.rs35
-rw-r--r--src/test/mir-opt/nll/reborrow-basic.rs39
2 files changed, 74 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);
             }
         }
 
diff --git a/src/test/mir-opt/nll/reborrow-basic.rs b/src/test/mir-opt/nll/reborrow-basic.rs
new file mode 100644
index 00000000000..1983478a4e1
--- /dev/null
+++ b/src/test/mir-opt/nll/reborrow-basic.rs
@@ -0,0 +1,39 @@
+// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Basic test for reborrow constraints: the region (`R5`) that appears
+// in the type of `r_a` must outlive the region (`R7`) that appears in
+// the type of `r_b`
+
+// compile-flags:-Znll -Zverbose
+//                     ^^^^^^^^^ force compiler to dump more region information
+
+#![allow(warnings)]
+
+fn use_x(_: &mut i32) -> bool { true }
+
+fn main() {
+    let mut foo: i32     = 22;
+    let r_a: &mut i32 = &mut foo;
+    let r_b: &mut i32 = &mut *r_a;
+    use_x(r_b);
+}
+
+// END RUST SOURCE
+// START rustc.node13.nll.0.mir
+// | R5: {bb0[6], bb0[7], bb0[8], bb0[9], bb0[10], bb0[11], bb0[12], bb0[13], bb0[14]}
+// ...
+// | R7: {bb0[11], bb0[12], bb0[13], bb0[14]}
+// END rustc.node13.nll.0.mir
+// START rustc.node13.nll.0.mir
+// let _2: &'_#5r mut i32;
+// ...
+// let _4: &'_#7r mut i32;
+// END rustc.node13.nll.0.mir