]> git.lizzy.rs Git - rust.git/commitdiff
Do not registor borrows for unsafe lvalues
authorKeith Yeung <kungfukeith11@gmail.com>
Thu, 16 Nov 2017 23:32:13 +0000 (15:32 -0800)
committerKeith Yeung <kungfukeith11@gmail.com>
Fri, 17 Nov 2017 22:16:37 +0000 (14:16 -0800)
src/librustc_mir/dataflow/impls/borrows.rs
src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs

index 928c07b7fbc05c2c37b712a2e632fe61b345f259..1e9d916def04491b88eded238f0f1fb6bf105ca0 100644 (file)
@@ -10,7 +10,7 @@
 
 use rustc::mir::{self, Location, Mir};
 use rustc::mir::visit::Visitor;
-use rustc::ty::{Region, TyCtxt};
+use rustc::ty::{self, Region, TyCtxt};
 use rustc::ty::RegionKind;
 use rustc::ty::RegionKind::ReScope;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
@@ -71,10 +71,14 @@ pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                mir: &'a Mir<'tcx>,
                nonlexical_regioncx: Option<&'a RegionInferenceContext<'tcx>>)
                -> Self {
-        let mut visitor = GatherBorrows { idx_vec: IndexVec::new(),
-                                          location_map: FxHashMap(),
-                                          region_map: FxHashMap(),
-                                          region_span_map: FxHashMap()};
+        let mut visitor = GatherBorrows {
+            tcx,
+            mir,
+            idx_vec: IndexVec::new(),
+            location_map: FxHashMap(),
+            region_map: FxHashMap(),
+            region_span_map: FxHashMap()
+        };
         visitor.visit_mir(mir);
         return Borrows { tcx: tcx,
                          mir: mir,
@@ -84,17 +88,22 @@ pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                          region_span_map: visitor.region_span_map,
                          nonlexical_regioncx };
 
-        struct GatherBorrows<'tcx> {
+        struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
+            tcx: TyCtxt<'a, 'gcx, 'tcx>,
+            mir: &'a Mir<'tcx>,
             idx_vec: IndexVec<BorrowIndex, BorrowData<'tcx>>,
             location_map: FxHashMap<Location, BorrowIndex>,
             region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
             region_span_map: FxHashMap<RegionKind, Span>,
         }
-        impl<'tcx> Visitor<'tcx> for GatherBorrows<'tcx> {
+
+        impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> {
             fn visit_rvalue(&mut self,
                             rvalue: &mir::Rvalue<'tcx>,
                             location: mir::Location) {
                 if let mir::Rvalue::Ref(region, kind, ref lvalue) = *rvalue {
+                    if is_unsafe_lvalue(self.tcx, self.mir, lvalue) { return; }
+
                     let borrow = BorrowData {
                         location: location, kind: kind, region: region, lvalue: lvalue.clone(),
                     };
@@ -197,7 +206,8 @@ fn statement_effect(&self,
             }
 
             mir::StatementKind::Assign(_, ref rhs) => {
-                if let mir::Rvalue::Ref(region, _, _) = *rhs {
+                if let mir::Rvalue::Ref(region, _, ref lvalue) = *rhs {
+                    if is_unsafe_lvalue(self.tcx, self.mir, lvalue) { return; }
                     let index = self.location_map.get(&location).unwrap_or_else(|| {
                         panic!("could not find BorrowIndex for location {:?}", location);
                     });
@@ -248,3 +258,35 @@ fn bottom_value() -> bool {
         false // bottom = no Rvalue::Refs are active by default
     }
 }
+
+fn is_unsafe_lvalue<'a, 'gcx: 'tcx, 'tcx: 'a>(
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    mir: &'a Mir<'tcx>,
+    lvalue: &mir::Lvalue<'tcx>
+) -> bool {
+    use self::mir::Lvalue::*;
+    use self::mir::ProjectionElem;
+
+    match *lvalue {
+        Local(_) => false,
+        Static(ref static_) => tcx.is_static_mut(static_.def_id),
+        Projection(ref proj) => {
+            match proj.elem {
+                ProjectionElem::Field(..) |
+                ProjectionElem::Downcast(..) |
+                ProjectionElem::Subslice { .. } |
+                ProjectionElem::ConstantIndex { .. } |
+                ProjectionElem::Index(_) => {
+                    is_unsafe_lvalue(tcx, mir, &proj.base)
+                }
+                ProjectionElem::Deref => {
+                    let ty = proj.base.ty(mir, tcx).to_ty(tcx);
+                    match ty.sty {
+                        ty::TyRawPtr(..) => true,
+                        _ => is_unsafe_lvalue(tcx, mir, &proj.base),
+                    }
+                }
+            }
+        }
+    }
+}
index 06d61242ec2f88ef892fd01916c9d174f30aa99b..d1cf08ac75463e0329cf78361f2e91c64ff22d95 100644 (file)
@@ -46,12 +46,6 @@ fn x(&mut self) -> &mut u32 {
     }
 }
 
-static mut sfoo : Foo = Foo{x: 23 };
-static mut sbar : Bar = Bar(23);
-static mut stuple : (i32, i32) = (24, 25);
-static mut senum : Baz = Baz::X(26);
-static mut sunion : U = U { a: 0 };
-
 fn main() {
     // Local and field from struct
     {
@@ -96,34 +90,6 @@ fn main() {
              //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed (Ast)
              //[mir]~| ERROR cannot use `u.a` because it was mutably borrowed (Mir)
     }
-    // Static and field from struct
-    unsafe {
-        let _x = sfoo.x();
-        sfoo.x; //[mir]~ ERROR cannot use `sfoo.x` because it was mutably borrowed (Mir)
-    }
-    // Static and field from tuple-struct
-    unsafe {
-        let _0 = sbar.x();
-        sbar.0; //[mir]~ ERROR cannot use `sbar.0` because it was mutably borrowed (Mir)
-    }
-    // Static and field from tuple
-    unsafe {
-        let _0 = &mut stuple.0;
-        stuple.0; //[mir]~ ERROR cannot use `stuple.0` because it was mutably borrowed (Mir)
-    }
-    // Static and field from enum
-    unsafe {
-        let _e0 = senum.x();
-        match senum {
-            Baz::X(value) => value
-            //[mir]~^ ERROR cannot use `senum.0` because it was mutably borrowed (Mir)
-        };
-    }
-    // Static and field from union
-    unsafe {
-        let _ra = &mut sunion.a;
-        sunion.a; //[mir]~ ERROR cannot use `sunion.a` because it was mutably borrowed (Mir)
-    }
     // Deref and field from struct
     {
         let mut f = Box::new(Foo { x: 22 });