about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2019-07-24 19:01:12 +0200
committerRalf Jung <post@ralfj.de>2019-08-02 22:33:36 +0200
commitec1e71895aa450606d99d7705dac20d689a330d1 (patch)
tree6b897f1f6f92ddae1d40e28892629764ce3aa4a0
parent48b87c6f275069e5c885b54e3d968056a5563db9 (diff)
turn cast_immediate into its own function
-rw-r--r--src/librustc_mir/interpret/cast.rs75
-rw-r--r--src/librustc_mir/interpret/operand.rs14
2 files changed, 54 insertions, 35 deletions
diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index e1842e72e3c..7e752e2edc4 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -11,7 +11,7 @@ use rustc::mir::interpret::{
 };
 use rustc::mir::CastKind;
 
-use super::{InterpCx, Machine, PlaceTy, OpTy, Immediate, FnVal};
+use super::{InterpCx, Machine, PlaceTy, OpTy, ImmTy, Immediate, FnVal};
 
 impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool {
@@ -37,40 +37,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
             Misc | Pointer(PointerCast::MutToConstPointer) => {
                 let src = self.read_immediate(src)?;
-
-                if self.type_is_fat_ptr(src.layout.ty) {
-                    match (*src, self.type_is_fat_ptr(dest.layout.ty)) {
-                        // pointers to extern types
-                        (Immediate::Scalar(_),_) |
-                        // slices and trait objects to other slices/trait objects
-                        (Immediate::ScalarPair(..), true) => {
-                            // No change to immediate
-                            self.write_immediate(*src, dest)?;
-                        }
-                        // slices and trait objects to thin pointers (dropping the metadata)
-                        (Immediate::ScalarPair(data, _), false) => {
-                            self.write_scalar(data, dest)?;
-                        }
-                    }
-                } else {
-                    match src.layout.variants {
-                        layout::Variants::Single { index } => {
-                            if let Some(discr) =
-                                src.layout.ty.discriminant_for_variant(*self.tcx, index)
-                            {
-                                // Cast from a univariant enum
-                                assert!(src.layout.is_zst());
-                                return self.write_scalar(
-                                    Scalar::from_uint(discr.val, dest.layout.size),
-                                    dest);
-                            }
-                        }
-                        layout::Variants::Multiple { .. } => {},
-                    }
-
-                    let dest_val = self.cast_scalar(src.to_scalar()?, src.layout, dest.layout)?;
-                    self.write_scalar(dest_val, dest)?;
-                }
+                let res = self.cast_immediate(src, dest.layout)?;
+                self.write_immediate(res, dest)?;
             }
 
             Pointer(PointerCast::ReifyFnPointer) => {
@@ -126,6 +94,43 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         Ok(())
     }
 
+    fn cast_immediate(
+        &self,
+        src: ImmTy<'tcx, M::PointerTag>,
+        dest_layout: TyLayout<'tcx>,
+    ) -> InterpResult<'tcx, Immediate<M::PointerTag>> {
+        if self.type_is_fat_ptr(src.layout.ty) {
+            return match (*src, self.type_is_fat_ptr(dest_layout.ty)) {
+                // pointers to extern types
+                (Immediate::Scalar(_),_) |
+                // slices and trait objects to other slices/trait objects
+                (Immediate::ScalarPair(..), true) => {
+                    // No change to immediate
+                    Ok(*src)
+                }
+                // slices and trait objects to thin pointers (dropping the metadata)
+                (Immediate::ScalarPair(data, _), false) => {
+                    Ok(data.into())
+                }
+            };
+        } else {
+            match src.layout.variants {
+                layout::Variants::Single { index } => {
+                    if let Some(discr) =
+                        src.layout.ty.discriminant_for_variant(*self.tcx, index)
+                    {
+                        // Cast from a univariant enum
+                        assert!(src.layout.is_zst());
+                        return Ok(Scalar::from_uint(discr.val, dest_layout.size).into());
+                    }
+                }
+                layout::Variants::Multiple { .. } => {},
+            }
+
+            return Ok(self.cast_scalar(src.to_scalar()?, src.layout, dest_layout)?.into());
+        }
+    }
+
     fn cast_scalar(
         &self,
         val: Scalar<M::PointerTag>,
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index e64a474b4ca..4742d53d0ba 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -32,6 +32,20 @@ pub enum Immediate<Tag=(), Id=AllocId> {
     ScalarPair(ScalarMaybeUndef<Tag, Id>, ScalarMaybeUndef<Tag, Id>),
 }
 
+impl<Tag> From<ScalarMaybeUndef<Tag>> for Immediate<Tag> {
+    #[inline(always)]
+    fn from(val: ScalarMaybeUndef<Tag>) -> Self {
+        Immediate::Scalar(val)
+    }
+}
+
+impl<Tag> From<Scalar<Tag>> for Immediate<Tag> {
+    #[inline(always)]
+    fn from(val: Scalar<Tag>) -> Self {
+        Immediate::Scalar(val.into())
+    }
+}
+
 impl<'tcx, Tag> Immediate<Tag> {
     #[inline]
     pub fn from_scalar(val: Scalar<Tag>) -> Self {