]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_mir/interpret/place.rs
Move def_id out add substsref
[rust.git] / src / librustc_mir / interpret / place.rs
index f66c4adf763976a33ad969e3681b219efa6b1f01..23c9e7fdf67ce7c692f62723408c1200e68f887f 100644 (file)
@@ -45,7 +45,7 @@ pub enum Place<Tag=(), Id=AllocId> {
 
 #[derive(Copy, Clone, Debug)]
 pub struct PlaceTy<'tcx, Tag=()> {
-    place: Place<Tag>,
+    place: Place<Tag>, // Keep this private, it helps enforce invariants
     pub layout: TyLayout<'tcx>,
 }
 
@@ -277,6 +277,10 @@ impl<'mir, 'tcx, Tag, M> InterpCx<'mir, 'tcx, M>
 {
     /// Take a value, which represents a (thin or fat) reference, and make it a place.
     /// Alignment is just based on the type.  This is the inverse of `MemPlace::to_ref()`.
+    ///
+    /// Only call this if you are sure the place is "valid" (aligned and inbounds), or do not
+    /// want to ever use the place for memory access!
+    /// Generally prefer `deref_operand`.
     pub fn ref_to_mplace(
         &self,
         val: ImmTy<'tcx, M::PointerTag>,
@@ -304,7 +308,8 @@ pub fn deref_operand(
     ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         let val = self.read_immediate(src)?;
         trace!("deref to {} on {:?}", val.layout.ty, *val);
-        self.ref_to_mplace(val)
+        let place = self.ref_to_mplace(val)?;
+        self.mplace_access_checked(place)
     }
 
     /// Check if the given place is good for memory access with the given
@@ -327,6 +332,23 @@ pub fn check_mplace_access(
         self.memory.check_ptr_access(place.ptr, size, place.align)
     }
 
+    /// Return the "access-checked" version of this `MPlace`, where for non-ZST
+    /// this is definitely a `Pointer`.
+    pub fn mplace_access_checked(
+        &self,
+        mut place: MPlaceTy<'tcx, M::PointerTag>,
+    ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
+        let (size, align) = self.size_and_align_of_mplace(place)?
+            .unwrap_or((place.layout.size, place.layout.align.abi));
+        assert!(place.mplace.align <= align, "dynamic alignment less strict than static one?");
+        place.mplace.align = align; // maximally strict checking
+        // When dereferencing a pointer, it must be non-NULL, aligned, and live.
+        if let Some(ptr) = self.check_mplace_access(place, Some(size))? {
+            place.mplace.ptr = ptr.into();
+        }
+        Ok(place)
+    }
+
     /// Force `place.ptr` to a `Pointer`.
     /// Can be helpful to avoid lots of `force_ptr` calls later, if this place is used a lot.
     pub fn force_mplace_ptr(
@@ -563,7 +585,7 @@ pub(super) fn eval_static_to_mplace(
         use rustc::mir::StaticKind;
 
         Ok(match place_static.kind {
-            StaticKind::Promoted(promoted) => {
+            StaticKind::Promoted(promoted, _) => {
                 let instance = self.frame().instance;
                 self.const_eval_raw(GlobalId {
                     instance,
@@ -571,11 +593,11 @@ pub(super) fn eval_static_to_mplace(
                 })?
             }
 
-            StaticKind::Static(def_id) => {
+            StaticKind::Static => {
                 let ty = place_static.ty;
                 assert!(!ty.needs_subst());
                 let layout = self.layout_of(ty)?;
-                let instance = ty::Instance::mono(*self.tcx, def_id);
+                let instance = ty::Instance::mono(*self.tcx, place_static.def_id);
                 let cid = GlobalId {
                     instance,
                     promoted: None
@@ -618,8 +640,11 @@ pub fn eval_place(
                         // their layout on return.
                         PlaceTy {
                             place: *return_place,
-                            layout: self
-                                .layout_of(self.monomorphize(self.frame().body.return_ty())?)?,
+                            layout: self.layout_of(
+                                self.subst_from_frame_and_normalize_erasing_regions(
+                                    self.frame().body.return_ty()
+                                )
+                            )?,
                         }
                     }
                     None => throw_unsup!(InvalidNullPointerUsage),
@@ -750,7 +775,9 @@ fn write_immediate_to_mplace_no_validate(
         // to handle padding properly, which is only correct if we never look at this data with the
         // wrong type.
 
-        let ptr = match self.check_mplace_access(dest, None)? {
+        let ptr = match self.check_mplace_access(dest, None)
+            .expect("places should be checked on creation")
+        {
             Some(ptr) => ptr,
             None => return Ok(()), // zero-sized access
         };
@@ -853,8 +880,10 @@ fn copy_op_no_validate(
         });
         assert_eq!(src.meta, dest.meta, "Can only copy between equally-sized instances");
 
-        let src = self.check_mplace_access(src, Some(size))?;
-        let dest = self.check_mplace_access(dest, Some(size))?;
+        let src = self.check_mplace_access(src, Some(size))
+            .expect("places should be checked on creation");
+        let dest = self.check_mplace_access(dest, Some(size))
+            .expect("places should be checked on creation");
         let (src_ptr, dest_ptr) = match (src, dest) {
             (Some(src_ptr), Some(dest_ptr)) => (src_ptr, dest_ptr),
             (None, None) => return Ok(()), // zero-sized copy