]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_mir/interpret/memory.rs
Auto merge of #69614 - estebank:ice-age, r=davidtwco
[rust.git] / src / librustc_mir / interpret / memory.rs
index 0bcdf9ae3c1f20866644e42a44dbfb534a32c90a..3c4a1857f9690e80fb69c60c4a91e33aa540e2be 100644 (file)
@@ -14,7 +14,7 @@
 use rustc::ty::{self, query::TyCtxtAt, Instance, ParamEnv};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 
-use syntax::ast::Mutability;
+use rustc_ast::ast::Mutability;
 
 use super::{
     AllocId, AllocMap, Allocation, AllocationExtra, CheckInAllocMsg, ErrorHandled, GlobalAlloc,
@@ -150,7 +150,8 @@ pub fn new(tcx: TyCtxtAt<'tcx>, extra: M::MemoryExtra) -> Self {
     /// through a pointer that was created by the program.
     #[inline]
     pub fn tag_static_base_pointer(&self, ptr: Pointer) -> Pointer<M::PointerTag> {
-        ptr.with_tag(M::tag_static_base_pointer(&self.extra, ptr.alloc_id))
+        let id = M::canonical_alloc_id(self, ptr.alloc_id);
+        ptr.with_tag(M::tag_static_base_pointer(&self.extra, id))
     }
 
     pub fn create_fn_alloc(
@@ -421,6 +422,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
     /// The `GlobalAlloc::Memory` branch here is still reachable though; when a static
     /// contains a reference to memory that was created during its evaluation (i.e., not to
     /// another static), those inner references only exist in "resolved" form.
+    ///
+    /// Assumes `id` is already canonical.
     fn get_static_alloc(
         memory_extra: &M::MemoryExtra,
         tcx: TyCtxtAt<'tcx>,
@@ -434,31 +437,30 @@ fn get_static_alloc(
             Some(GlobalAlloc::Static(def_id)) => {
                 // We got a "lazy" static that has not been computed yet.
                 if tcx.is_foreign_item(def_id) {
-                    trace!("static_alloc: foreign item {:?}", def_id);
-                    M::find_foreign_static(tcx.tcx, def_id)?
-                } else {
-                    trace!("static_alloc: Need to compute {:?}", def_id);
-                    let instance = Instance::mono(tcx.tcx, def_id);
-                    let gid = GlobalId { instance, promoted: None };
-                    // use the raw query here to break validation cycles. Later uses of the static
-                    // will call the full query anyway
-                    let raw_const =
-                        tcx.const_eval_raw(ty::ParamEnv::reveal_all().and(gid)).map_err(|err| {
-                            // no need to report anything, the const_eval call takes care of that
-                            // for statics
-                            assert!(tcx.is_static(def_id));
-                            match err {
-                                ErrorHandled::Reported => err_inval!(ReferencedConstant),
-                                ErrorHandled::TooGeneric => err_inval!(TooGeneric),
-                            }
-                        })?;
-                    // Make sure we use the ID of the resolved memory, not the lazy one!
-                    let id = raw_const.alloc_id;
-                    let allocation = tcx.alloc_map.lock().unwrap_memory(id);
-
-                    M::before_access_static(memory_extra, allocation)?;
-                    Cow::Borrowed(allocation)
+                    trace!("get_static_alloc: foreign item {:?}", def_id);
+                    throw_unsup!(ReadForeignStatic)
                 }
+                trace!("get_static_alloc: Need to compute {:?}", def_id);
+                let instance = Instance::mono(tcx.tcx, def_id);
+                let gid = GlobalId { instance, promoted: None };
+                // use the raw query here to break validation cycles. Later uses of the static
+                // will call the full query anyway
+                let raw_const =
+                    tcx.const_eval_raw(ty::ParamEnv::reveal_all().and(gid)).map_err(|err| {
+                        // no need to report anything, the const_eval call takes care of that
+                        // for statics
+                        assert!(tcx.is_static(def_id));
+                        match err {
+                            ErrorHandled::Reported => err_inval!(ReferencedConstant),
+                            ErrorHandled::TooGeneric => err_inval!(TooGeneric),
+                        }
+                    })?;
+                // Make sure we use the ID of the resolved memory, not the lazy one!
+                let id = raw_const.alloc_id;
+                let allocation = tcx.alloc_map.lock().unwrap_memory(id);
+
+                M::before_access_static(memory_extra, allocation)?;
+                Cow::Borrowed(allocation)
             }
         };
         // We got tcx memory. Let the machine initialize its "extra" stuff.
@@ -478,6 +480,7 @@ pub fn get_raw(
         &self,
         id: AllocId,
     ) -> InterpResult<'tcx, &Allocation<M::PointerTag, M::AllocExtra>> {
+        let id = M::canonical_alloc_id(self, id);
         // The error type of the inner closure here is somewhat funny.  We have two
         // ways of "erroring": An actual error, or because we got a reference from
         // `get_static_alloc` that we can actually use directly without inserting anything anywhere.
@@ -513,6 +516,7 @@ pub fn get_raw_mut(
         &mut self,
         id: AllocId,
     ) -> InterpResult<'tcx, &mut Allocation<M::PointerTag, M::AllocExtra>> {
+        let id = M::canonical_alloc_id(self, id);
         let tcx = self.tcx;
         let memory_extra = &self.extra;
         let a = self.alloc_map.get_mut_or(id, || {
@@ -550,6 +554,7 @@ pub fn get_size_and_align(
         id: AllocId,
         liveness: AllocCheck,
     ) -> InterpResult<'static, (Size, Align)> {
+        let id = M::canonical_alloc_id(self, id);
         // # Regular allocations
         // Don't use `self.get_raw` here as that will
         // a) cause cycles in case `id` refers to a static
@@ -560,7 +565,7 @@ pub fn get_size_and_align(
 
         // # Function pointers
         // (both global from `alloc_map` and local from `extra_fn_ptr_map`)
-        if let Ok(_) = self.get_fn_alloc(id) {
+        if self.get_fn_alloc(id).is_some() {
             return if let AllocCheck::Dereferenceable = liveness {
                 // The caller requested no function pointers.
                 throw_unsup!(DerefFunctionPointer)
@@ -602,14 +607,15 @@ pub fn get_size_and_align(
         }
     }
 
-    fn get_fn_alloc(&self, id: AllocId) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> {
+    /// Assumes `id` is already canonical.
+    fn get_fn_alloc(&self, id: AllocId) -> Option<FnVal<'tcx, M::ExtraFnVal>> {
         trace!("reading fn ptr: {}", id);
         if let Some(extra) = self.extra_fn_ptr_map.get(&id) {
-            Ok(FnVal::Other(*extra))
+            Some(FnVal::Other(*extra))
         } else {
             match self.tcx.alloc_map.lock().get(id) {
-                Some(GlobalAlloc::Function(instance)) => Ok(FnVal::Instance(instance)),
-                _ => throw_unsup!(ExecuteMemory),
+                Some(GlobalAlloc::Function(instance)) => Some(FnVal::Instance(instance)),
+                _ => None,
             }
         }
     }
@@ -622,7 +628,8 @@ pub fn get_fn(
         if ptr.offset.bytes() != 0 {
             throw_unsup!(InvalidFunctionPointer)
         }
-        self.get_fn_alloc(ptr.alloc_id)
+        let id = M::canonical_alloc_id(self, ptr.alloc_id);
+        self.get_fn_alloc(id).ok_or_else(|| err_unsup!(ExecuteMemory).into())
     }
 
     pub fn mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> {