Rollup merge of #121997 - RalfJung:cast-float-ty, r=compiler-errors

interpret/cast: make more matches on FloatTy properly exhaustive

Actually implementing these is pretty trivial (at least once all the scalar methods are added, which happens in https://github.com/rust-lang/rust/pull/121926), but I'm staying consistent with the other f16/f128 PRs. Also adding adding all the tests to Miri would be quite a lot of work.

There's probably some way to reduce the code duplication here with more use of generics... but that's a future refactor.^^

r? ```@tgross35```
This commit is contained in:
Matthias Krüger 2024-03-05 06:40:33 +01:00 committed by GitHub
commit 92ff43d87b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -182,13 +182,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
use rustc_type_ir::TyKind::*;
let val = match src.layout.ty.kind() {
// Floating point
Float(FloatTy::F32) => self.cast_from_float(src.to_scalar().to_f32()?, cast_to.ty),
Float(FloatTy::F64) => self.cast_from_float(src.to_scalar().to_f64()?, cast_to.ty),
_ => {
bug!("Can't cast 'Float' type into {}", cast_to.ty);
}
let Float(fty) = src.layout.ty.kind() else {
bug!("FloatToFloat/FloatToInt cast: source type {} is not a float type", src.layout.ty)
};
let val = match fty {
FloatTy::F16 => unimplemented!("f16_f128"),
FloatTy::F32 => self.cast_from_float(src.to_scalar().to_f32()?, cast_to.ty),
FloatTy::F64 => self.cast_from_float(src.to_scalar().to_f64()?, cast_to.ty),
FloatTy::F128 => unimplemented!("f16_f128"),
};
Ok(ImmTy::from_scalar(val, cast_to))
}
@ -275,6 +276,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
trace!("cast_from_scalar: {}, {} -> {}", v, src_layout.ty, cast_ty);
Ok(match *cast_ty.kind() {
// int -> int
Int(_) | Uint(_) => {
let size = match *cast_ty.kind() {
Int(t) => Integer::from_int_ty(self, t).size(),
@ -285,15 +287,26 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Scalar::from_uint(v, size)
}
Float(FloatTy::F32) if signed => Scalar::from_f32(Single::from_i128(v as i128).value),
Float(FloatTy::F64) if signed => Scalar::from_f64(Double::from_i128(v as i128).value),
Float(FloatTy::F32) => Scalar::from_f32(Single::from_u128(v).value),
Float(FloatTy::F64) => Scalar::from_f64(Double::from_u128(v).value),
Char => {
// `u8` to `char` cast
Scalar::from_u32(u8::try_from(v).unwrap().into())
// signed int -> float
Float(fty) if signed => {
let v = v as i128;
match fty {
FloatTy::F16 => unimplemented!("f16_f128"),
FloatTy::F32 => Scalar::from_f32(Single::from_i128(v).value),
FloatTy::F64 => Scalar::from_f64(Double::from_i128(v).value),
FloatTy::F128 => unimplemented!("f16_f128"),
}
}
// unsigned int -> float
Float(fty) => match fty {
FloatTy::F16 => unimplemented!("f16_f128"),
FloatTy::F32 => Scalar::from_f32(Single::from_u128(v).value),
FloatTy::F64 => Scalar::from_f64(Double::from_u128(v).value),
FloatTy::F128 => unimplemented!("f16_f128"),
},
// u8 -> char
Char => Scalar::from_u32(u8::try_from(v).unwrap().into()),
// Casts to bool are not permitted by rustc, no need to handle them here.
_ => span_bug!(self.cur_span(), "invalid int to {} cast", cast_ty),
@ -339,14 +352,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let v = f.to_i128(size.bits_usize()).value;
Scalar::from_int(v, size)
}
// float -> f32
Float(FloatTy::F32) => {
Scalar::from_f32(adjust_nan(self, f, f.convert(&mut false).value))
}
// float -> f64
Float(FloatTy::F64) => {
Scalar::from_f64(adjust_nan(self, f, f.convert(&mut false).value))
}
// float -> float
Float(fty) => match fty {
FloatTy::F16 => unimplemented!("f16_f128"),
FloatTy::F32 => Scalar::from_f32(adjust_nan(self, f, f.convert(&mut false).value)),
FloatTy::F64 => Scalar::from_f64(adjust_nan(self, f, f.convert(&mut false).value)),
FloatTy::F128 => unimplemented!("f16_f128"),
},
// That's it.
_ => span_bug!(self.cur_span(), "invalid float to {} cast", dest_ty),
}