about summary refs log tree commit diff
diff options
context:
space:
mode:
authorouz-a <oguz.agcayazi@gmail.com>2022-10-16 21:30:32 +0300
committerouz-a <oguz.agcayazi@gmail.com>2022-10-23 18:47:16 +0300
commit4bd98443ed368a781812545915cf758e2091128d (patch)
tree02e6c43265b55326cb6ef95097f0607cfa5365d9
parentd59c7ff000db581bd03c2da79046af431678fab8 (diff)
downloadrust-4bd98443ed368a781812545915cf758e2091128d.tar.gz
rust-4bd98443ed368a781812545915cf758e2091128d.zip
remove misc_cast and validate types
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs63
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs25
-rw-r--r--src/tools/miri/src/shims/intrinsics/simd.rs6
3 files changed, 66 insertions, 28 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index 764224fd007..f980e606b93 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -42,10 +42,22 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let res = self.pointer_from_exposed_address_cast(&src, cast_ty)?;
                 self.write_immediate(res, dest)?;
             }
-            // FIXME: We shouldn't use `misc_cast` for these but handle them separately.
-            IntToInt | FloatToInt | FloatToFloat | IntToFloat | FnPtrToPtr | PtrToPtr => {
+
+            IntToInt | IntToFloat => {
                 let src = self.read_immediate(src)?;
-                let res = self.misc_cast(&src, cast_ty)?;
+                let res = self.int_to_int_or_float(&src, cast_ty)?;
+                self.write_immediate(res, dest)?;
+            }
+
+            FloatToFloat | FloatToInt => {
+                let src = self.read_immediate(src)?;
+                let res = self.float_to_float_or_int(&src, cast_ty)?;
+                self.write_immediate(res, dest)?;
+            }
+
+            FnPtrToPtr | PtrToPtr => {
+                let src = self.read_immediate(&src)?;
+                let res = self.ptr_to_ptr(&src, cast_ty)?;
                 self.write_immediate(res, dest)?;
             }
 
@@ -126,13 +138,27 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         Ok(())
     }
 
-    pub fn misc_cast(
+    pub fn int_to_int_or_float(
+        &mut self,
+        src: &ImmTy<'tcx, M::Provenance>,
+        cast_ty: Ty<'tcx>,
+    ) -> InterpResult<'tcx, Immediate<M::Provenance>> {
+        if (src.layout.ty.is_integral() || src.layout.ty.is_char() || src.layout.ty.is_bool())
+            && (cast_ty.is_floating_point() || cast_ty.is_integral() || cast_ty.is_char())
+        {
+            let scalar = src.to_scalar();
+            Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into())
+        } else {
+            bug!("Unexpected cast from type {:?}", src.layout.ty)
+        }
+    }
+
+    pub fn float_to_float_or_int(
         &mut self,
         src: &ImmTy<'tcx, M::Provenance>,
         cast_ty: Ty<'tcx>,
     ) -> InterpResult<'tcx, Immediate<M::Provenance>> {
         use rustc_type_ir::sty::TyKind::*;
-        trace!("Casting {:?}: {:?} to {:?}", *src, src.layout.ty, cast_ty);
 
         match src.layout.ty.kind() {
             // Floating point
@@ -142,19 +168,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             Float(FloatTy::F64) => {
                 return Ok(self.cast_from_float(src.to_scalar().to_f64()?, cast_ty).into());
             }
-            // The rest is integer/pointer-"like", including fn ptr casts
-            _ => assert!(
-                src.layout.ty.is_bool()
-                    || src.layout.ty.is_char()
-                    || src.layout.ty.is_integral()
-                    || src.layout.ty.is_any_ptr(),
-                "Unexpected cast from type {:?}",
-                src.layout.ty
-            ),
+            _ => {
+                bug!("Can't cast 'Float' type into {:?}", cast_ty);
+            }
         }
+    }
 
-        // # First handle non-scalar source values.
-
+    /// Handles 'FnPtrToPtr' and 'PtrToPtr' casts.
+    pub fn ptr_to_ptr(
+        &mut self,
+        src: &ImmTy<'tcx, M::Provenance>,
+        cast_ty: Ty<'tcx>,
+    ) -> InterpResult<'tcx, Immediate<M::Provenance>> {
         // Handle casting any ptr to raw ptr (might be a fat ptr).
         if src.layout.ty.is_any_ptr() && cast_ty.is_unsafe_ptr() {
             let dest_layout = self.layout_of(cast_ty)?;
@@ -178,11 +203,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)),
                 };
             }
+        } else {
+            bug!("Can't cast 'Ptr' or 'FnPtr' into {:?}", cast_ty);
         }
-
-        // # The remaining source values are scalar and "int-like".
-        let scalar = src.to_scalar();
-        Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into())
     }
 
     pub fn pointer_expose_address_cast(
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 8abf767f89f..40946344a35 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -556,21 +556,36 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 check_kinds!(a, "Cannot shallow init type {:?}", ty::RawPtr(..));
             }
             Rvalue::Cast(kind, operand, target_type) => {
+                let op_ty = operand.ty(self.body, self.tcx);
                 match kind {
                     CastKind::DynStar => {
                         // FIXME(dyn-star): make sure nothing needs to be done here.
                     }
-                    // Nothing to check here
+                    // FIXME: Add Checks for these
                     CastKind::PointerFromExposedAddress
                     | CastKind::PointerExposeAddress
                     | CastKind::Pointer(_) => {}
-                    _ => {
-                        let op_ty = operand.ty(self.body, self.tcx);
-                        if op_ty.is_enum() {
+                    CastKind::IntToInt | CastKind::IntToFloat => {
+                        let input_valid = op_ty.is_integral() || op_ty.is_char() || op_ty.is_bool();
+                        let target_valid = target_type.is_numeric() || target_type.is_char();
+                        if !input_valid || !target_valid {
+                            self.fail(
+                                location,
+                                format!("Wrong cast kind {kind:?} for the type {op_ty}",),
+                            );
+                        }
+                    }
+                    CastKind::FnPtrToPtr | CastKind::PtrToPtr => {
+                        if !(op_ty.is_any_ptr() && target_type.is_unsafe_ptr()) {
+                            self.fail(location, "Can't cast {op_ty} into 'Ptr'");
+                        }
+                    }
+                    CastKind::FloatToFloat | CastKind::FloatToInt => {
+                        if !op_ty.is_floating_point() || !target_type.is_numeric() {
                             self.fail(
                                 location,
                                 format!(
-                                    "enum -> int casts should go through `Rvalue::Discriminant`: {operand:?}:{op_ty} as {target_type}",
+                                    "Trying to cast non 'Float' as {kind:?} into {target_type:?}"
                                 ),
                             );
                         }
diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs
index 163d185f66f..c1b949b1f79 100644
--- a/src/tools/miri/src/shims/intrinsics/simd.rs
+++ b/src/tools/miri/src/shims/intrinsics/simd.rs
@@ -437,13 +437,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     let val = match (op.layout.ty.kind(), dest.layout.ty.kind()) {
                         // Int-to-(int|float): always safe
                         (ty::Int(_) | ty::Uint(_), ty::Int(_) | ty::Uint(_) | ty::Float(_)) =>
-                            this.misc_cast(&op, dest.layout.ty)?,
+                            this.int_to_int_or_float(&op, dest.layout.ty)?,
                         // Float-to-float: always safe
                         (ty::Float(_), ty::Float(_)) =>
-                            this.misc_cast(&op, dest.layout.ty)?,
+                            this.float_to_float_or_int(&op, dest.layout.ty)?,
                         // Float-to-int in safe mode
                         (ty::Float(_), ty::Int(_) | ty::Uint(_)) if safe_cast =>
-                            this.misc_cast(&op, dest.layout.ty)?,
+                            this.float_to_float_or_int(&op, dest.layout.ty)?,
                         // Float-to-int in unchecked mode
                         (ty::Float(FloatTy::F32), ty::Int(_) | ty::Uint(_)) if !safe_cast =>
                             this.float_to_int_unchecked(op.to_scalar().to_f32()?, dest.layout.ty)?.into(),