about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2022-03-06 14:01:01 -0500
committerRalf Jung <post@ralfj.de>2022-03-06 14:01:01 -0500
commitd29d2307b95dcde3c089949d9d4b4c3fdcc2c325 (patch)
tree557082f31dcf1c2336ba1337af869e841ffe4d13
parentc274e4969f058b1c644243181ece9f829efa7594 (diff)
downloadrust-d29d2307b95dcde3c089949d9d4b4c3fdcc2c325.tar.gz
rust-d29d2307b95dcde3c089949d9d4b4c3fdcc2c325.zip
CTFE engine: expose misc_cast to Miri
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs10
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs11
2 files changed, 13 insertions, 8 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index e2c4eb1dadc..5be0a183cf6 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -97,7 +97,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         Ok(())
     }
 
-    fn misc_cast(
+    pub fn misc_cast(
         &self,
         src: &ImmTy<'tcx, M::PointerTag>,
         cast_ty: Ty<'tcx>,
@@ -139,7 +139,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 if let Some(discr) = src.layout.ty.discriminant_for_variant(*self.tcx, index) {
                     assert!(src.layout.is_zst());
                     let discr_layout = self.layout_of(discr.ty)?;
-                    return Ok(self.cast_from_scalar(discr.val, discr_layout, cast_ty).into());
+                    return Ok(self.cast_from_int_like(discr.val, discr_layout, cast_ty).into());
                 }
             }
             Variants::Multiple { .. } => {}
@@ -169,17 +169,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
         }
 
-        // # The remaining source values are scalar.
+        // # The remaining source values are scalar and "int-like".
 
         // For all remaining casts, we either
         // (a) cast a raw ptr to usize, or
         // (b) cast from an integer-like (including bool, char, enums).
         // In both cases we want the bits.
         let bits = src.to_scalar()?.to_bits(src.layout.size)?;
-        Ok(self.cast_from_scalar(bits, src.layout, cast_ty).into())
+        Ok(self.cast_from_int_like(bits, src.layout, cast_ty).into())
     }
 
-    pub(super) fn cast_from_scalar(
+    fn cast_from_int_like(
         &self,
         v: u128, // raw bits (there is no ScalarTy so we separate data+layout)
         src_layout: TyAndLayout<'tcx>,
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index 16870489176..fb4fe41bdbc 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -681,18 +681,22 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         let tag_val = self.read_immediate(&self.operand_field(op, tag_field)?)?;
         assert_eq!(tag_layout.size, tag_val.layout.size);
         assert_eq!(tag_layout.abi.is_signed(), tag_val.layout.abi.is_signed());
-        let tag_val = tag_val.to_scalar()?;
-        trace!("tag value: {:?}", tag_val);
+        trace!("tag value: {}", tag_val);
 
         // Figure out which discriminant and variant this corresponds to.
         Ok(match *tag_encoding {
             TagEncoding::Direct => {
+                // Generate a specific error if `tag_val` is not an integer.
+                // (`tag_bits` itself is only used for error messages below.)
                 let tag_bits = tag_val
+                    .to_scalar()?
                     .try_to_int()
                     .map_err(|dbg_val| err_ub!(InvalidTag(dbg_val)))?
                     .assert_bits(tag_layout.size);
                 // Cast bits from tag layout to discriminant layout.
-                let discr_val = self.cast_from_scalar(tag_bits, tag_layout, discr_layout.ty);
+                // After the checks we did above, this cannot fail.
+                let discr_val =
+                    self.misc_cast(&tag_val, discr_layout.ty).unwrap().to_scalar().unwrap();
                 let discr_bits = discr_val.assert_bits(discr_layout.size);
                 // Convert discriminant to variant index, and catch invalid discriminants.
                 let index = match *op.layout.ty.kind() {
@@ -712,6 +716,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 (discr_val, index.0)
             }
             TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start } => {
+                let tag_val = tag_val.to_scalar()?;
                 // Compute the variant this niche value/"tag" corresponds to. With niche layout,
                 // discriminant (encoded in niche/tag) and variant index are the same.
                 let variants_start = niche_variants.start().as_u32();