Rollup merge of #70487 - Mark-Simulacrum:float-unchecked-casts, r=SimonSapin
Stabilize float::to_int_unchecked This renames and stabilizes unsafe floating point to integer casts, which are intended to be the substitute for the currently unsound `as` behavior, once that changes to safe-but-slower saturating casts. As such, I believe this also likely unblocks #10184 (our oldest I-unsound issue!), as once this rolls out to stable it would be far easier IMO to change the behavior of `as` to be safe by default. This does not stabilize the trait or the associated method, as they are deemed internal implementation details (and consumers should not, generally, want to expose them, as in practice all callers likely know statically/without generics what the return type is). Closes #67058
This commit is contained in:
commit
1eabbd024c
@ -13,9 +13,9 @@ pub trait Sealed {}
|
||||
/// Typically doesn’t need to be used directly.
|
||||
#[unstable(feature = "convert_float_to_int", issue = "67057")]
|
||||
pub trait FloatToInt<Int>: private::Sealed + Sized {
|
||||
#[unstable(feature = "float_approx_unchecked_to", issue = "67058")]
|
||||
#[unstable(feature = "convert_float_to_int", issue = "67057")]
|
||||
#[doc(hidden)]
|
||||
unsafe fn approx_unchecked(self) -> Int;
|
||||
unsafe fn to_int_unchecked(self) -> Int;
|
||||
}
|
||||
|
||||
macro_rules! impl_float_to_int {
|
||||
@ -27,8 +27,15 @@ impl private::Sealed for $Float {}
|
||||
impl FloatToInt<$Int> for $Float {
|
||||
#[doc(hidden)]
|
||||
#[inline]
|
||||
unsafe fn approx_unchecked(self) -> $Int {
|
||||
crate::intrinsics::float_to_int_approx_unchecked(self)
|
||||
unsafe fn to_int_unchecked(self) -> $Int {
|
||||
#[cfg(bootstrap)]
|
||||
{
|
||||
crate::intrinsics::float_to_int_approx_unchecked(self)
|
||||
}
|
||||
#[cfg(not(bootstrap))]
|
||||
{
|
||||
crate::intrinsics::float_to_int_unchecked(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
)+
|
||||
|
@ -1582,8 +1582,16 @@
|
||||
/// Convert with LLVM’s fptoui/fptosi, which may return undef for values out of range
|
||||
/// (<https://github.com/rust-lang/rust/issues/10184>)
|
||||
/// This is under stabilization at <https://github.com/rust-lang/rust/issues/67058>
|
||||
#[cfg(bootstrap)]
|
||||
pub fn float_to_int_approx_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
||||
|
||||
/// Convert with LLVM’s fptoui/fptosi, which may return undef for values out of range
|
||||
/// (<https://github.com/rust-lang/rust/issues/10184>)
|
||||
///
|
||||
/// Stabilized as `f32::to_int_unchecked` and `f64::to_int_unchecked`.
|
||||
#[cfg(not(bootstrap))]
|
||||
pub fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
|
||||
|
||||
/// Returns the number of bits set in an integer type `T`
|
||||
///
|
||||
/// The stabilized versions of this intrinsic are available on the integer
|
||||
|
@ -464,14 +464,12 @@ pub fn min(self, other: f32) -> f32 {
|
||||
/// assuming that the value is finite and fits in that type.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(float_approx_unchecked_to)]
|
||||
///
|
||||
/// let value = 4.6_f32;
|
||||
/// let rounded = unsafe { value.approx_unchecked_to::<u16>() };
|
||||
/// let rounded = unsafe { value.to_int_unchecked::<u16>() };
|
||||
/// assert_eq!(rounded, 4);
|
||||
///
|
||||
/// let value = -128.9_f32;
|
||||
/// let rounded = unsafe { value.approx_unchecked_to::<i8>() };
|
||||
/// let rounded = unsafe { value.to_int_unchecked::<i8>() };
|
||||
/// assert_eq!(rounded, std::i8::MIN);
|
||||
/// ```
|
||||
///
|
||||
@ -482,13 +480,13 @@ pub fn min(self, other: f32) -> f32 {
|
||||
/// * Not be `NaN`
|
||||
/// * Not be infinite
|
||||
/// * Be representable in the return type `Int`, after truncating off its fractional part
|
||||
#[unstable(feature = "float_approx_unchecked_to", issue = "67058")]
|
||||
#[stable(feature = "float_approx_unchecked_to", since = "1.44.0")]
|
||||
#[inline]
|
||||
pub unsafe fn approx_unchecked_to<Int>(self) -> Int
|
||||
pub unsafe fn to_int_unchecked<Int>(self) -> Int
|
||||
where
|
||||
Self: FloatToInt<Int>,
|
||||
{
|
||||
FloatToInt::<Int>::approx_unchecked(self)
|
||||
FloatToInt::<Int>::to_int_unchecked(self)
|
||||
}
|
||||
|
||||
/// Raw transmutation to `u32`.
|
||||
|
@ -478,14 +478,12 @@ pub fn min(self, other: f64) -> f64 {
|
||||
/// assuming that the value is finite and fits in that type.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(float_approx_unchecked_to)]
|
||||
///
|
||||
/// let value = 4.6_f32;
|
||||
/// let rounded = unsafe { value.approx_unchecked_to::<u16>() };
|
||||
/// let rounded = unsafe { value.to_int_unchecked::<u16>() };
|
||||
/// assert_eq!(rounded, 4);
|
||||
///
|
||||
/// let value = -128.9_f32;
|
||||
/// let rounded = unsafe { value.approx_unchecked_to::<i8>() };
|
||||
/// let rounded = unsafe { value.to_int_unchecked::<i8>() };
|
||||
/// assert_eq!(rounded, std::i8::MIN);
|
||||
/// ```
|
||||
///
|
||||
@ -496,13 +494,13 @@ pub fn min(self, other: f64) -> f64 {
|
||||
/// * Not be `NaN`
|
||||
/// * Not be infinite
|
||||
/// * Be representable in the return type `Int`, after truncating off its fractional part
|
||||
#[unstable(feature = "float_approx_unchecked_to", issue = "67058")]
|
||||
#[stable(feature = "float_approx_unchecked_to", since = "1.44.0")]
|
||||
#[inline]
|
||||
pub unsafe fn approx_unchecked_to<Int>(self) -> Int
|
||||
pub unsafe fn to_int_unchecked<Int>(self) -> Int
|
||||
where
|
||||
Self: FloatToInt<Int>,
|
||||
{
|
||||
FloatToInt::<Int>::approx_unchecked(self)
|
||||
FloatToInt::<Int>::to_int_unchecked(self)
|
||||
}
|
||||
|
||||
/// Raw transmutation to `u64`.
|
||||
|
@ -543,13 +543,13 @@ fn codegen_intrinsic_call(
|
||||
}
|
||||
}
|
||||
|
||||
"float_to_int_approx_unchecked" => {
|
||||
"float_to_int_unchecked" => {
|
||||
if float_type_width(arg_tys[0]).is_none() {
|
||||
span_invalid_monomorphization_error(
|
||||
tcx.sess,
|
||||
span,
|
||||
&format!(
|
||||
"invalid monomorphization of `float_to_int_approx_unchecked` \
|
||||
"invalid monomorphization of `float_to_int_unchecked` \
|
||||
intrinsic: expected basic float type, \
|
||||
found `{}`",
|
||||
arg_tys[0]
|
||||
@ -570,7 +570,7 @@ fn codegen_intrinsic_call(
|
||||
tcx.sess,
|
||||
span,
|
||||
&format!(
|
||||
"invalid monomorphization of `float_to_int_approx_unchecked` \
|
||||
"invalid monomorphization of `float_to_int_unchecked` \
|
||||
intrinsic: expected basic integer type, \
|
||||
found `{}`",
|
||||
ret_ty
|
||||
|
@ -275,7 +275,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
||||
"fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => {
|
||||
(1, vec![param(0), param(0)], param(0))
|
||||
}
|
||||
"float_to_int_approx_unchecked" => (2, vec![param(0)], param(1)),
|
||||
"float_to_int_unchecked" => (2, vec![param(0)], param(1)),
|
||||
|
||||
"assume" => (0, vec![tcx.types.bool], tcx.mk_unit()),
|
||||
"likely" => (0, vec![tcx.types.bool], tcx.types.bool),
|
||||
|
Loading…
Reference in New Issue
Block a user