diff options
| -rw-r--r-- | src/librustc_mir/const_eval.rs | 6 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/machine.rs | 11 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/operand.rs | 10 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/place.rs | 37 |
4 files changed, 45 insertions, 19 deletions
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 362fbc4b135..41a70c88f56 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -472,7 +472,7 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> _ptr: Pointer<Self::PointerTag>, _pointee_ty: Ty<'tcx>, _pointee_size: Size, - _borrow_kind: Option<mir::BorrowKind>, + _borrow_kind: Option<hir::Mutability>, ) -> EvalResult<'tcx, Self::PointerTag> { Ok(()) } @@ -481,7 +481,9 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> fn tag_dereference( _ecx: &EvalContext<'a, 'mir, 'tcx, Self>, _ptr: Pointer<Self::PointerTag>, - _ptr_ty: Ty<'tcx>, + _pointee_ty: Ty<'tcx>, + _pointee_size: Size, + _borrow_kind: Option<hir::Mutability>, ) -> EvalResult<'tcx, Self::PointerTag> { Ok(()) } diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 1318bbe1c2b..7184be6cd16 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -15,7 +15,7 @@ use std::borrow::{Borrow, Cow}; use std::hash::Hash; -use rustc::hir::def_id::DefId; +use rustc::hir::{self, def_id::DefId}; use rustc::mir; use rustc::ty::{self, Ty, layout::{Size, TyLayout}, query::TyCtxtAt}; @@ -206,21 +206,24 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { /// Executed when evaluating the `&` operator: Creating a new reference. /// This has the chance to adjust the tag. - /// `borrow_kind` can be `None` in case a raw ptr is being created. + /// `mutability` can be `None` in case a raw ptr is being created. fn tag_reference( ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, ptr: Pointer<Self::PointerTag>, pointee_ty: Ty<'tcx>, pointee_size: Size, - borrow_kind: Option<mir::BorrowKind>, + mutability: Option<hir::Mutability>, ) -> EvalResult<'tcx, Self::PointerTag>; /// Executed when evaluating the `*` operator: Following a reference. /// This has the change to adjust the tag. + /// `mutability` can be `None` in case a raw ptr is being dereferenced. fn tag_dereference( ecx: &EvalContext<'a, 'mir, 'tcx, Self>, ptr: Pointer<Self::PointerTag>, - ptr_ty: Ty<'tcx>, + pointee_ty: Ty<'tcx>, + pointee_size: Size, + mutability: Option<hir::Mutability>, ) -> EvalResult<'tcx, Self::PointerTag>; /// Execute a validation operation diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 021e2d58f84..d0a32161485 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -217,6 +217,16 @@ impl<'tcx, Tag> Value<Tag> { Value::ScalarPair(ptr, _) => ptr.not_undef(), } } + + /// Convert the value into its metadata. + /// Throws away the first half of a ScalarPair! + #[inline] + pub fn to_meta(self) -> EvalResult<'tcx, Option<Scalar<Tag>>> { + Ok(match self { + Value::Scalar(_) => None, + Value::ScalarPair(_, meta) => Some(meta.not_undef()?), + }) + } } // ScalarPair needs a type to interpret, so we often have a value and a type together diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 4fa08e8c311..0bd9094ebcd 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -15,6 +15,7 @@ use std::convert::TryFrom; use std::hash::Hash; +use rustc::hir; use rustc::mir; use rustc::ty::{self, Ty}; use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout}; @@ -270,26 +271,31 @@ where &self, val: ValTy<'tcx, M::PointerTag>, ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { + let pointee_type = val.layout.ty.builtin_deref(true).unwrap().ty; + let layout = self.layout_of(pointee_type)?; + + let align = layout.align; + let meta = val.to_meta()?; + let ptr = match val.to_scalar_ptr()? { Scalar::Ptr(ptr) if M::ENABLE_PTR_TRACKING_HOOKS => { // Machine might want to track the `*` operator - let tag = M::tag_dereference(self, ptr, val.layout.ty)?; + let (size, _) = self.size_and_align_of(meta, layout)? + .expect("ref_to_mplace cannot determine size"); + let mutbl = match val.layout.ty.sty { + // `builtin_deref` considers boxes immutable, that's useless for our purposes + ty::Ref(_, _, mutbl) => Some(mutbl), + ty::Adt(def, _) if def.is_box() => Some(hir::MutMutable), + ty::RawPtr(_) => None, + _ => bug!("Unexpected pointer type {}", val.layout.ty.sty), + }; + let tag = M::tag_dereference(self, ptr, pointee_type, size, mutbl)?; Scalar::Ptr(Pointer::new_with_tag(ptr.alloc_id, ptr.offset, tag)) } other => other, }; - let pointee_type = val.layout.ty.builtin_deref(true).unwrap().ty; - let layout = self.layout_of(pointee_type)?; - let align = layout.align; - - let mplace = match *val { - Value::Scalar(_) => - MemPlace { ptr, align, meta: None }, - Value::ScalarPair(_, meta) => - MemPlace { ptr, align, meta: Some(meta.not_undef()?) }, - }; - Ok(MPlaceTy { mplace, layout }) + Ok(MPlaceTy { mplace: MemPlace { ptr, align, meta }, layout }) } /// Turn a mplace into a (thin or fat) pointer, as a reference, pointing to the same space. @@ -304,7 +310,12 @@ where // Machine might want to track the `&` operator let (size, _) = self.size_and_align_of_mplace(place)? .expect("create_ref cannot determine size"); - let tag = M::tag_reference(self, ptr, place.layout.ty, size, borrow_kind)?; + let mutbl = match borrow_kind { + Some(mir::BorrowKind::Mut { .. }) => Some(hir::MutMutable), + Some(_) => Some(hir::MutImmutable), + None => None, + }; + let tag = M::tag_reference(self, ptr, place.layout.ty, size, mutbl)?; Scalar::Ptr(Pointer::new_with_tag(ptr.alloc_id, ptr.offset, tag)) }, other => other, |
