about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Scherer <github35764891676564198441@oli-obk.de>2019-07-26 10:34:54 +0200
committerOliver Scherer <github35764891676564198441@oli-obk.de>2019-07-26 10:34:54 +0200
commit3bc1d01bb9d81fa3682186d8ace06becaa8cac8c (patch)
treef651baf3d2c168e46a2c286a40189a09576ac1b5
parent34e7a3cc4dcb7ddd404b9566047a78d1e234f137 (diff)
downloadrust-3bc1d01bb9d81fa3682186d8ace06becaa8cac8c.tar.gz
rust-3bc1d01bb9d81fa3682186d8ace06becaa8cac8c.zip
Clear up `get_size_and_align`
-rw-r--r--src/librustc_mir/interpret/memory.rs71
1 files changed, 37 insertions, 34 deletions
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 4ac5920c60e..9140c90bed3 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -535,41 +535,44 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         id: AllocId,
         liveness: AllocCheck,
     ) -> InterpResult<'static, (Size, Align)> {
-        let alloc_or_size_align = self.alloc_map.get_or(id, || {
-            // Can't do this in the match argument, we may get cycle errors since the lock would
-            // be held throughout the match.
-            let alloc = self.tcx.alloc_map.lock().get(id);
-            Err(match alloc {
-                Some(GlobalAlloc::Static(did)) => {
-                    // Use size and align of the type
-                    let ty = self.tcx.type_of(did);
-                    let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
-                    Ok((layout.size, layout.align.abi))
-                },
-                Some(GlobalAlloc::Memory(alloc)) =>
-                    // this duplicates the logic on the `match alloc_or_size_align`, but due to the
-                    // API of `get_or` there's no way around that.
-                    Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)),
-                Some(GlobalAlloc::Function(_)) => if let AllocCheck::Dereferencable = liveness {
-                    // The caller requested no function pointers.
-                    err!(DerefFunctionPointer)
-                } else {
-                    Ok((Size::ZERO, Align::from_bytes(1).unwrap()))
-                },
-                // The rest must be dead.
-                None => if let AllocCheck::MaybeDead = liveness {
-                    // Deallocated pointers are allowed, we should be able to find
-                    // them in the map.
-                    Ok(*self.dead_alloc_map.get(&id)
-                        .expect("deallocated pointers should all be recorded in `dead_alloc_map`"))
-                } else {
-                    err!(DanglingPointerDeref)
-                },
-            })
-        });
-        match alloc_or_size_align {
+        // Don't use `self.get` here as that will
+        // a) cause cycles in case `id` refers to a static
+        // b) duplicate a static's allocation in miri
+        match self.alloc_map.get_or(id, || Err(())) {
             Ok((_, alloc)) => Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)),
-            Err(done) => done,
+            Err(()) => {
+                // Can't do this in the match argument, we may get cycle errors since the lock would
+                // be held throughout the match.
+                let alloc = self.tcx.alloc_map.lock().get(id);
+                match alloc {
+                    Some(GlobalAlloc::Static(did)) => {
+                        // Use size and align of the type
+                        let ty = self.tcx.type_of(did);
+                        let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
+                        return Ok((layout.size, layout.align.abi));
+                    },
+                    Some(GlobalAlloc::Memory(alloc)) =>
+                        // Need to duplicate the logic here, because the global allocations have
+                        // different associated types than the interpreter-local ones
+                        Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)),
+                    Some(GlobalAlloc::Function(_)) => if let AllocCheck::Dereferencable = liveness {
+                        // The caller requested no function pointers.
+                        return err!(DerefFunctionPointer);
+                    } else {
+                        return Ok((Size::ZERO, Align::from_bytes(1).unwrap()));
+                    },
+                    // The rest must be dead.
+                    None => return if let AllocCheck::MaybeDead = liveness {
+                        // Deallocated pointers are allowed, we should be able to find
+                        // them in the map.
+                        Ok(*self.dead_alloc_map.get(&id)
+                            .expect("deallocated pointers should all be recorded in \
+                                    `dead_alloc_map`"))
+                    } else {
+                        err!(DanglingPointerDeref)
+                    },
+                }
+            }
         }
     }