about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_mir/const_eval.rs6
-rw-r--r--src/librustc_mir/interpret/machine.rs11
-rw-r--r--src/librustc_mir/interpret/operand.rs10
-rw-r--r--src/librustc_mir/interpret/place.rs37
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,