From d29d2307b95dcde3c089949d9d4b4c3fdcc2c325 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 6 Mar 2022 14:01:01 -0500 Subject: [PATCH] CTFE engine: expose misc_cast to Miri --- compiler/rustc_const_eval/src/interpret/cast.rs | 10 +++++----- compiler/rustc_const_eval/src/interpret/operand.rs | 11 ++++++++--- 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 e2c4eb1dadc83..5be0a183cf6b4 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 16870489176d7..fb4fe41bdbc4c 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();