about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2018-01-15 12:47:26 +0100
committerFelix S. Klock II <pnkfelix@pnkfx.org>2018-02-08 12:16:25 +0100
commitc00266b7ac97a8c04136e14f10eb70fb64ec2c94 (patch)
tree039c47192cc088e324251295e0353d44c5fa4812 /src
parent4f93357d3b8938dfe439329c43c1e4f919a70869 (diff)
downloadrust-c00266b7ac97a8c04136e14f10eb70fb64ec2c94.tar.gz
rust-c00266b7ac97a8c04136e14f10eb70fb64ec2c94.zip
Encode (in MIR) whether borrows are explicit in source or arise due to autoref.
This is foundation for issue 46747 (limit two-phase borrows to method-call autorefs).
Diffstat (limited to 'src')
-rw-r--r--src/librustc/ich/impls_mir.rs20
-rw-r--r--src/librustc/mir/mod.rs8
-rw-r--r--src/librustc/mir/tcx.rs2
-rw-r--r--src/librustc/mir/visit.rs6
-rw-r--r--src/librustc_const_eval/pattern.rs4
-rw-r--r--src/librustc_mir/borrow_check/error_reporting.rs8
-rw-r--r--src/librustc_mir/borrow_check/mod.rs14
-rw-r--r--src/librustc_mir/dataflow/impls/borrows.rs2
-rw-r--r--src/librustc_mir/hair/cx/expr.rs15
-rw-r--r--src/librustc_mir/shim.rs5
-rw-r--r--src/librustc_mir/transform/inline.rs4
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs2
-rw-r--r--src/librustc_mir/util/elaborate_drops.rs10
-rw-r--r--src/librustc_trans/mir/constant.rs2
14 files changed, 67 insertions, 35 deletions
diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs
index f46b590d2dc..03a369577a3 100644
--- a/src/librustc/ich/impls_mir.rs
+++ b/src/librustc/ich/impls_mir.rs
@@ -20,7 +20,6 @@ use std::mem;
 impl_stable_hash_for!(struct mir::GeneratorLayout<'tcx> { fields });
 impl_stable_hash_for!(struct mir::SourceInfo { span, scope });
 impl_stable_hash_for!(enum mir::Mutability { Mut, Not });
-impl_stable_hash_for!(enum mir::BorrowKind { Shared, Unique, Mut });
 impl_stable_hash_for!(enum mir::LocalKind { Var, Temp, Arg, ReturnPointer });
 impl_stable_hash_for!(struct mir::LocalDecl<'tcx> {
     mutability,
@@ -37,6 +36,25 @@ impl_stable_hash_for!(struct mir::UnsafetyViolation { source_info, description,
 impl_stable_hash_for!(struct mir::UnsafetyCheckResult { violations, unsafe_blocks });
 
 impl<'gcx> HashStable<StableHashingContext<'gcx>>
+for mir::BorrowKind {
+    #[inline]
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hasher: &mut StableHasher<W>) {
+        mem::discriminant(self).hash_stable(hcx, hasher);
+
+        match *self {
+            mir::BorrowKind::Shared |
+            mir::BorrowKind::Unique => {}
+            mir::BorrowKind::Mut { allow_two_phase_borrow } => {
+                allow_two_phase_borrow.hash_stable(hcx, hasher);
+            }
+        }
+    }
+}
+
+
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for mir::UnsafetyViolationKind {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index d82691f882c..70bfc1e2d32 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -413,7 +413,11 @@ pub enum BorrowKind {
     Unique,
 
     /// Data is mutable and not aliasable.
-    Mut,
+    Mut {
+        /// True if this borrow arose from method-call auto-ref
+        /// (i.e. `adjustment::Adjust::Borrow`)
+        allow_two_phase_borrow: bool
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -1611,7 +1615,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
             Ref(region, borrow_kind, ref place) => {
                 let kind_str = match borrow_kind {
                     BorrowKind::Shared => "",
-                    BorrowKind::Mut | BorrowKind::Unique => "mut ",
+                    BorrowKind::Mut { .. } | BorrowKind::Unique => "mut ",
                 };
 
                 // When printing regions, add trailing space if necessary.
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index 53607764b39..5433c54fb94 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -264,7 +264,7 @@ impl<'tcx> BinOp {
 impl BorrowKind {
     pub fn to_mutbl_lossy(self) -> hir::Mutability {
         match self {
-            BorrowKind::Mut => hir::MutMutable,
+            BorrowKind::Mut { .. } => hir::MutMutable,
             BorrowKind::Shared => hir::MutImmutable,
 
             // We have no type corresponding to a unique imm borrow, so
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 57ed41f2f06..afaf7d41e92 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -951,9 +951,10 @@ impl<'tcx> PlaceContext<'tcx> {
     pub fn is_mutating_use(&self) -> bool {
         match *self {
             PlaceContext::Store | PlaceContext::AsmOutput | PlaceContext::Call |
-            PlaceContext::Borrow { kind: BorrowKind::Mut, .. } |
+            PlaceContext::Borrow { kind: BorrowKind::Mut { .. }, .. } |
             PlaceContext::Projection(Mutability::Mut) |
             PlaceContext::Drop => true,
+
             PlaceContext::Inspect |
             PlaceContext::Borrow { kind: BorrowKind::Shared, .. } |
             PlaceContext::Borrow { kind: BorrowKind::Unique, .. } |
@@ -971,7 +972,8 @@ impl<'tcx> PlaceContext<'tcx> {
             PlaceContext::Borrow { kind: BorrowKind::Unique, .. } |
             PlaceContext::Projection(Mutability::Not) |
             PlaceContext::Copy | PlaceContext::Move => true,
-            PlaceContext::Borrow { kind: BorrowKind::Mut, .. } | PlaceContext::Store |
+
+            PlaceContext::Borrow { kind: BorrowKind::Mut { .. }, .. } | PlaceContext::Store |
             PlaceContext::AsmOutput |
             PlaceContext::Call | PlaceContext::Projection(Mutability::Mut) |
             PlaceContext::Drop | PlaceContext::StorageLive | PlaceContext::StorageDead |
diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs
index e0b3929e32a..bdb1001124d 100644
--- a/src/librustc_const_eval/pattern.rs
+++ b/src/librustc_const_eval/pattern.rs
@@ -134,7 +134,7 @@ impl<'tcx> fmt::Display for Pattern<'tcx> {
                     BindingMode::ByValue => mutability == Mutability::Mut,
                     BindingMode::ByRef(_, bk) => {
                         write!(f, "ref ")?;
-                        bk == BorrowKind::Mut
+                        match bk { BorrowKind::Mut { .. } => true, _ => false }
                     }
                 };
                 if is_mut {
@@ -429,7 +429,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
                         (Mutability::Not, BindingMode::ByValue),
                     ty::BindByReference(hir::MutMutable) =>
                         (Mutability::Not, BindingMode::ByRef(
-                            region.unwrap(), BorrowKind::Mut)),
+                            region.unwrap(), BorrowKind::Mut { allow_two_phase_borrow: false })),
                     ty::BindByReference(hir::MutImmutable) =>
                         (Mutability::Not, BindingMode::ByRef(
                             region.unwrap(), BorrowKind::Shared)),
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index 1ea897bf27c..34551e8e76f 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -256,8 +256,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             "immutable",
             "mutable",
         ) {
-            (BorrowKind::Shared, lft, _, BorrowKind::Mut, _, rgt) |
-            (BorrowKind::Mut, _, lft, BorrowKind::Shared, rgt, _) => self.tcx
+            (BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt) |
+            (BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => self.tcx
                 .cannot_reborrow_already_borrowed(
                     span,
                     &desc_place,
@@ -271,7 +271,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     Origin::Mir,
                 ),
 
-            (BorrowKind::Mut, _, _, BorrowKind::Mut, _, _) => self.tcx
+            (BorrowKind::Mut { .. }, _, _, BorrowKind::Mut { .. }, _, _) => self.tcx
                 .cannot_mutably_borrow_multiply(
                     span,
                     &desc_place,
@@ -314,7 +314,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     Origin::Mir,
                 ),
 
-            (BorrowKind::Mut, _, lft, BorrowKind::Unique, _, _) => self.tcx
+            (BorrowKind::Mut { .. }, _, lft, BorrowKind::Unique, _, _) => self.tcx
                 .cannot_reborrow_already_uniquely_borrowed(
                     span,
                     &desc_place,
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index d90209993aa..647cf178310 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -797,7 +797,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     Control::Continue
                 }
 
-                (Read(kind), BorrowKind::Unique) | (Read(kind), BorrowKind::Mut) => {
+                (Read(kind), BorrowKind::Unique) | (Read(kind), BorrowKind::Mut { .. }) => {
                     // Reading from mere reservations of mutable-borrows is OK.
                     if this.tcx.sess.two_phase_borrows() && index.is_reservation()
                     {
@@ -828,7 +828,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 }
 
                 (Reservation(kind), BorrowKind::Unique)
-                | (Reservation(kind), BorrowKind::Mut)
+                | (Reservation(kind), BorrowKind::Mut { .. })
                 | (Activation(kind, _), _)
                 | (Write(kind), _) => {
                     match rw {
@@ -945,7 +945,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             Rvalue::Ref(_ /*rgn*/, bk, ref place) => {
                 let access_kind = match bk {
                     BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))),
-                    BorrowKind::Unique | BorrowKind::Mut => {
+                    BorrowKind::Unique | BorrowKind::Mut { .. } => {
                         let wk = WriteKind::MutableBorrow(bk);
                         if self.tcx.sess.two_phase_borrows() {
                             (Deep, Reservation(wk))
@@ -1196,7 +1196,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 // mutable borrow before we check it.
                 match borrow.kind {
                     BorrowKind::Shared => return,
-                    BorrowKind::Unique | BorrowKind::Mut => {}
+                    BorrowKind::Unique | BorrowKind::Mut { .. } => {}
                 }
 
                 self.access_place(
@@ -1467,8 +1467,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     span_bug!(span, "&unique borrow for {:?} should not fail", place);
                 }
             }
-            Reservation(WriteKind::MutableBorrow(BorrowKind::Mut))
-            | Write(WriteKind::MutableBorrow(BorrowKind::Mut)) => if let Err(place_err) =
+            Reservation(WriteKind::MutableBorrow(BorrowKind::Mut { .. }))
+            | Write(WriteKind::MutableBorrow(BorrowKind::Mut { .. })) => if let Err(place_err) =
                 self.is_mutable(place, is_local_mutation_allowed)
             {
                 error_reported = true;
@@ -1532,7 +1532,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             Activation(..) => {} // permission checks are done at Reservation point.
 
             Read(ReadKind::Borrow(BorrowKind::Unique))
-            | Read(ReadKind::Borrow(BorrowKind::Mut))
+            | Read(ReadKind::Borrow(BorrowKind::Mut { .. }))
             | Read(ReadKind::Borrow(BorrowKind::Shared))
             | Read(ReadKind::Copy) => {} // Access authorized
         }
diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index 80990bcc080..fe9b0b86bef 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -122,7 +122,7 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> {
         let kind = match self.kind {
             mir::BorrowKind::Shared => "",
             mir::BorrowKind::Unique => "uniq ",
-            mir::BorrowKind::Mut => "mut ",
+            mir::BorrowKind::Mut { .. } => "mut ",
         };
         let region = format!("{}", self.region);
         let region = if region.len() > 0 { format!("{} ", region) } else { region };
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 317b038c482..e33147a915b 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -21,6 +21,7 @@ use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
 use rustc::ty::cast::CastKind as TyCastKind;
 use rustc::hir;
 use rustc::hir::def_id::LocalDefId;
+use rustc::mir::{BorrowKind};
 
 impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
     type Output = Expr<'tcx>;
@@ -111,7 +112,7 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 span,
                 kind: ExprKind::Borrow {
                     region: deref.region,
-                    borrow_kind: to_borrow_kind(deref.mutbl),
+                    borrow_kind: to_borrow_kind(deref.mutbl, true),
                     arg: expr.to_ref(),
                 },
             };
@@ -121,7 +122,7 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         Adjust::Borrow(AutoBorrow::Ref(r, m)) => {
             ExprKind::Borrow {
                 region: r,
-                borrow_kind: to_borrow_kind(m),
+                borrow_kind: to_borrow_kind(m, true),
                 arg: expr.to_ref(),
             }
         }
@@ -141,7 +142,7 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 span,
                 kind: ExprKind::Borrow {
                     region,
-                    borrow_kind: to_borrow_kind(m),
+                    borrow_kind: to_borrow_kind(m, true),
                     arg: expr.to_ref(),
                 },
             };
@@ -287,7 +288,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             };
             ExprKind::Borrow {
                 region,
-                borrow_kind: to_borrow_kind(mutbl),
+                borrow_kind: to_borrow_kind(mutbl, false),
                 arg: expr.to_ref(),
             }
         }
@@ -642,9 +643,9 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     }
 }
 
-fn to_borrow_kind(m: hir::Mutability) -> BorrowKind {
+fn to_borrow_kind(m: hir::Mutability, allow_two_phase_borrow: bool) -> BorrowKind {
     match m {
-        hir::MutMutable => BorrowKind::Mut,
+        hir::MutMutable => BorrowKind::Mut { allow_two_phase_borrow },
         hir::MutImmutable => BorrowKind::Shared,
     }
 }
@@ -947,7 +948,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             let borrow_kind = match upvar_borrow.kind {
                 ty::BorrowKind::ImmBorrow => BorrowKind::Shared,
                 ty::BorrowKind::UniqueImmBorrow => BorrowKind::Unique,
-                ty::BorrowKind::MutBorrow => BorrowKind::Mut,
+                ty::BorrowKind::MutBorrow => BorrowKind::Mut { allow_two_phase_borrow: false }
             };
             Expr {
                 temp_lifetime,
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 42ffcc194ca..e6ebdd3d6c1 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -716,11 +716,14 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 }),
                 span
             ));
+            let borrow_kind = BorrowKind::Mut {
+                allow_two_phase_borrow: false,
+            };
             statements.push(Statement {
                 source_info,
                 kind: StatementKind::Assign(
                     Place::Local(ref_rcvr),
-                    Rvalue::Ref(tcx.types.re_erased, BorrowKind::Mut, rcvr_l)
+                    Rvalue::Ref(tcx.types.re_erased, borrow_kind, rcvr_l)
                 )
             });
             Operand::Move(Place::Local(ref_rcvr))
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index ceea97e3ed3..15bbcad7325 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -426,7 +426,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
                     debug!("Creating temp for return destination");
                     let dest = Rvalue::Ref(
                         self.tcx.types.re_erased,
-                        BorrowKind::Mut,
+                        BorrowKind::Mut { allow_two_phase_borrow: false },
                         destination.0);
 
                     let ty = dest.ty(caller_mir, self.tcx);
@@ -511,7 +511,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
                          callsite: &CallSite<'tcx>, caller_mir: &mut Mir<'tcx>) -> Local {
         let arg = Rvalue::Ref(
             self.tcx.types.re_erased,
-            BorrowKind::Mut,
+            BorrowKind::Mut { allow_two_phase_borrow: false },
             arg.deref());
 
         let ty = arg.ty(caller_mir, self.tcx);
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index da76adfd48f..d4ef90a7d7c 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -600,7 +600,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                 }
 
                 let ty = place.ty(self.mir, self.tcx).to_ty(self.tcx);
-                if kind == BorrowKind::Mut {
+                if let BorrowKind::Mut { .. } = kind {
                     // In theory, any zero-sized value could be borrowed
                     // mutably without consequences. However, only &mut []
                     // is allowed right now, and only in functions.
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index 65771068014..e2feb0ed390 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -531,7 +531,9 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
         let result = BasicBlockData {
             statements: vec![self.assign(
                 &Place::Local(ref_place),
-                Rvalue::Ref(tcx.types.re_erased, BorrowKind::Mut, self.place.clone())
+                Rvalue::Ref(tcx.types.re_erased,
+                            BorrowKind::Mut { allow_two_phase_borrow: false },
+                            self.place.clone())
             )],
             terminator: Some(Terminator {
                 kind: TerminatorKind::Call {
@@ -591,7 +593,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
         } else {
             (Rvalue::Ref(
                  tcx.types.re_erased,
-                 BorrowKind::Mut,
+                 BorrowKind::Mut { allow_two_phase_borrow: false },
                  self.place.clone().index(cur)),
              Rvalue::BinaryOp(BinOp::Add, copy(&Place::Local(cur)), one))
         };
@@ -735,7 +737,9 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
             // cur = tmp as *mut T;
             // end = Offset(cur, len);
             drop_block_stmts.push(self.assign(&tmp, Rvalue::Ref(
-                tcx.types.re_erased, BorrowKind::Mut, self.place.clone()
+                tcx.types.re_erased,
+                BorrowKind::Mut { allow_two_phase_borrow: false },
+                self.place.clone()
             )));
             drop_block_stmts.push(self.assign(&cur, Rvalue::Cast(
                 CastKind::Misc, Operand::Move(tmp.clone()), iter_ty
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index cd1975488a2..49b4ef0d385 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -870,7 +870,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                         } else {
                             self.cx.tcx.data_layout.pointer_align
                         };
-                        if bk == mir::BorrowKind::Mut {
+                        if let mir::BorrowKind::Mut { .. } = bk {
                             consts::addr_of_mut(self.cx, llval, align, "ref_mut")
                         } else {
                             consts::addr_of(self.cx, llval, align, "ref")