about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-08-07 18:01:29 -0400
committerNiko Matsakis <niko@alum.mit.edu>2018-08-08 04:51:50 -0400
commit1bae4f5aecbd6c7a4daa09540e7e71f73b9a5c7a (patch)
tree5e90f302b902b8a46f20e0a278ba6f4d9c9dcf4c
parent3b7989d1dffb0d1b36dd8f4a7b11ea98ed7dc2ba (diff)
downloadrust-1bae4f5aecbd6c7a4daa09540e7e71f73b9a5c7a.tar.gz
rust-1bae4f5aecbd6c7a4daa09540e7e71f73b9a5c7a.zip
optimize redundant borrows
-rw-r--r--src/librustc_mir/borrow_check/borrow_set.rs2
-rw-r--r--src/librustc_mir/borrow_check/place_ext.rs26
-rw-r--r--src/librustc_mir/dataflow/impls/borrows.rs2
3 files changed, 22 insertions, 8 deletions
diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs
index fe33dc0a58a..2e0cbf4326b 100644
--- a/src/librustc_mir/borrow_check/borrow_set.rs
+++ b/src/librustc_mir/borrow_check/borrow_set.rs
@@ -159,7 +159,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> {
         location: mir::Location,
     ) {
         if let mir::Rvalue::Ref(region, kind, ref borrowed_place) = *rvalue {
-            if borrowed_place.is_unsafe_place(self.tcx, self.mir) {
+            if borrowed_place.ignore_borrow(self.tcx, self.mir) {
                 return;
             }
 
diff --git a/src/librustc_mir/borrow_check/place_ext.rs b/src/librustc_mir/borrow_check/place_ext.rs
index b0517c5e61f..be0091068c2 100644
--- a/src/librustc_mir/borrow_check/place_ext.rs
+++ b/src/librustc_mir/borrow_check/place_ext.rs
@@ -15,8 +15,11 @@ use rustc::ty::{self, TyCtxt};
 
 /// Extension methods for the `Place` type.
 crate trait PlaceExt<'tcx> {
-    /// True if this is a deref of a raw pointer.
-    fn is_unsafe_place(&self, tcx: TyCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>) -> bool;
+    /// Returns true if we can safely ignore borrows of this place.
+    /// This is true whenever there is no action that the user can do
+    /// to the place `self` that would invalidate the borrow. This is true
+    /// for borrows of raw pointer dereferents as well as shared references.
+    fn ignore_borrow(&self, tcx: TyCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>) -> bool;
 
     /// If this is a place like `x.f.g`, returns the local
     /// `x`. Returns `None` if this is based in a static.
@@ -24,7 +27,7 @@ crate trait PlaceExt<'tcx> {
 }
 
 impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
-    fn is_unsafe_place(&self, tcx: TyCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>) -> bool {
+    fn ignore_borrow(&self, tcx: TyCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>) -> bool {
         match self {
             Place::Promoted(_) |
             Place::Local(_) => false,
@@ -36,12 +39,23 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
                 | ProjectionElem::Downcast(..)
                 | ProjectionElem::Subslice { .. }
                 | ProjectionElem::ConstantIndex { .. }
-                | ProjectionElem::Index(_) => proj.base.is_unsafe_place(tcx, mir),
+                | ProjectionElem::Index(_) => proj.base.ignore_borrow(tcx, mir),
+
                 ProjectionElem::Deref => {
                     let ty = proj.base.ty(mir, tcx).to_ty(tcx);
                     match ty.sty {
-                        ty::TyRawPtr(..) => true,
-                        _ => proj.base.is_unsafe_place(tcx, mir),
+                        // For both derefs of raw pointers and `&T`
+                        // references, the original path is `Copy` and
+                        // therefore not significant.  In particular,
+                        // there is nothing the user can do to the
+                        // original path that would invalidate the
+                        // newly created reference -- and if there
+                        // were, then the user could have copied the
+                        // original path into a new variable and
+                        // borrowed *that* one, leaving the original
+                        // path unborrowed.
+                        ty::TyRawPtr(..) | ty::TyRef(_, _, hir::MutImmutable) => true,
+                        _ => proj.base.ignore_borrow(tcx, mir),
                     }
                 }
             },
diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index ea59e42fd47..b0c4d37814e 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -233,7 +233,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
                 // propagate_call_return method.
 
                 if let mir::Rvalue::Ref(region, _, ref place) = *rhs {
-                    if place.is_unsafe_place(self.tcx, self.mir) { return; }
+                    if place.ignore_borrow(self.tcx, self.mir) { return; }
                     let index = self.borrow_set.location_map.get(&location).unwrap_or_else(|| {
                         panic!("could not find BorrowIndex for location {:?}", location);
                     });