about summary refs log tree commit diff
path: root/compiler/rustc_const_eval
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2023-08-17 18:59:39 +0200
committerRalf Jung <post@ralfj.de>2023-08-30 13:46:55 +0200
commitf87e91de7db20e1c3804f7d90c487bd83ef80d76 (patch)
tree1666fd82e731904b7f1f9c786dc2fe380c468d02 /compiler/rustc_const_eval
parent7cdeff266c9b95f509588d89ffb5558b12c2dd94 (diff)
downloadrust-f87e91de7db20e1c3804f7d90c487bd83ef80d76.tar.gz
rust-f87e91de7db20e1c3804f7d90c487bd83ef80d76.zip
unify passing of sized and unsized function arguments :-)
Diffstat (limited to 'compiler/rustc_const_eval')
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs32
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs34
2 files changed, 35 insertions, 31 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 58674a1eec5..babc5790f9e 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -912,15 +912,24 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         Ok(())
     }
 
-    /// Mark a storage as live, killing the previous content.
-    pub fn storage_live(&mut self, local: mir::Local) -> InterpResult<'tcx> {
+    pub fn storage_live_dyn(
+        &mut self,
+        local: mir::Local,
+        meta: MemPlaceMeta<M::Provenance>,
+    ) -> InterpResult<'tcx> {
         trace!("{:?} is now live", local);
 
-        if self.layout_of_local(self.frame(), local, None)?.is_unsized() {
-            throw_unsup!(UnsizedLocal);
-        }
+        let layout = self.layout_of_local(self.frame(), local, None)?;
+        let local_val = LocalValue::Live(if layout.is_sized() {
+            assert!(matches!(meta, MemPlaceMeta::None)); // we're dropping the metadata
+            // Just make this an efficient immediate.
+            Operand::Immediate(Immediate::Uninit)
+        } else {
+            // Need to allocate some memory.
+            let dest_place = self.allocate_dyn(layout, MemoryKind::Stack, meta)?;
+            Operand::Indirect(*dest_place)
+        });
 
-        let local_val = LocalValue::Live(Operand::Immediate(Immediate::Uninit));
         // StorageLive expects the local to be dead, and marks it live.
         let old = mem::replace(&mut self.frame_mut().locals[local].value, local_val);
         if !matches!(old, LocalValue::Dead) {
@@ -929,6 +938,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         Ok(())
     }
 
+    /// Mark a storage as live, killing the previous content.
+    pub fn storage_live(&mut self, local: mir::Local) -> InterpResult<'tcx> {
+        trace!("{:?} is now live", local);
+
+        if self.layout_of_local(self.frame(), local, None)?.is_unsized() {
+            throw_unsup!(UnsizedLocal);
+        }
+
+        self.storage_live_dyn(local, MemPlaceMeta::None)
+    }
+
     pub fn storage_dead(&mut self, local: mir::Local) -> InterpResult<'tcx> {
         assert!(local != mir::RETURN_PLACE, "Cannot make return place dead");
         trace!("{:?} is now dead", local);
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index fd65758b064..279a06d3868 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -1,5 +1,4 @@
 use std::borrow::Cow;
-use std::mem;
 
 use either::Either;
 use rustc_ast::ast::InlineAsmOptions;
@@ -15,8 +14,8 @@ use rustc_target::abi::{self, FieldIdx};
 use rustc_target::spec::abi::Abi;
 
 use super::{
-    AllocId, FnVal, ImmTy, InterpCx, InterpResult, LocalValue, MPlaceTy, Machine, MemoryKind, OpTy,
-    Operand, PlaceTy, Provenance, Scalar, StackPopCleanup,
+    AllocId, FnVal, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, PlaceTy, Projectable,
+    Provenance, Scalar, StackPopCleanup,
 };
 use crate::fluent_generated as fluent;
 
@@ -394,28 +393,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // did in-place of by-copy argument passing, except for pointer equality tests.
         let caller_arg_copy = self.copy_fn_arg(&caller_arg)?;
         if !already_live {
-            // Special handling for unsized parameters: they are harder to make live.
-            if caller_arg_copy.layout.is_unsized() {
-                // `check_argument_compat` ensures that both have the same type, so we know they will use the metadata the same way.
-                assert_eq!(caller_arg_copy.layout.ty, callee_ty);
-                // We have to properly pre-allocate the memory for the callee.
-                // So let's tear down some abstractions.
-                // This all has to be in memory, there are no immediate unsized values.
-                let src = caller_arg_copy.assert_mem_place();
-                // The destination cannot be one of these "spread args".
-                let dest_local = callee_arg.as_local().expect("unsized arguments cannot be spread");
-                // Allocate enough memory to hold `src`.
-                let dest_place = self.allocate_dyn(src.layout, MemoryKind::Stack, src.meta)?;
-                // Update the local to be that new place. This is essentially a "dyn-sized StorageLive".
-                let old = mem::replace(
-                    &mut self.frame_mut().locals[dest_local].value,
-                    LocalValue::Live(Operand::Indirect(*dest_place)),
-                );
-                assert!(matches!(old, LocalValue::Dead));
-            } else {
-                // Just make the local live.
-                self.storage_live(callee_arg.as_local().unwrap())?;
-            }
+            let local = callee_arg.as_local().unwrap();
+            let meta = caller_arg_copy.meta();
+            // `check_argument_compat` ensures that if metadata is needed, both have the same type,
+            // so we know they will use the metadata the same way.
+            assert!(!meta.has_meta() || caller_arg_copy.layout.ty == callee_ty);
+
+            self.storage_live_dyn(local, meta)?;
         }
         // Now we can finally actually evaluate the callee place.
         let callee_arg = self.eval_place(*callee_arg)?;