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, @@ -36,6 +35,25 @@ impl_stable_hash_for!(struct mir::BasicBlockData<'tcx> { statements, terminator, impl_stable_hash_for!(struct mir::UnsafetyViolation { source_info, description, kind }); impl_stable_hash_for!(struct mir::UnsafetyCheckResult { violations, unsafe_blocks }); +impl<'gcx> HashStable> +for mir::BorrowKind { + #[inline] + fn hash_stable(&self, + hcx: &mut StableHashingContext<'gcx>, + hasher: &mut StableHasher) { + 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> for mir::UnsafetyViolationKind { #[inline] 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")