Mark some f16 and f128 functions unstably const · model-checking/verify-rust-std@14c24b1 (original) (raw)

`@@ -12,6 +12,8 @@

`

12

12

`#![unstable(feature = "f16", issue = "116909")]

`

13

13

``

14

14

`use crate::convert::FloatToInt;

`

``

15

`+

#[cfg(not(test))]

`

``

16

`+

use crate::intrinsics;

`

15

17

`use crate::mem;

`

16

18

`use crate::num::FpCategory;

`

17

19

``

`@@ -788,12 +790,52 @@ impl f16 {

`

788

790

```` /// ```


`789`

`791`

`#[inline]

`

`790`

`792`

`#[unstable(feature = "f16", issue = "116909")]

`

``

`793`

`+

#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]

`

`791`

`794`

`#[must_use = "this returns the result of the operation, without modifying the original"]

`

`792`

``

`-

pub fn to_bits(self) -> u16 {

`

`793`

``

`` -

// SAFETY: `u16` is a plain old datatype so we can always... uh...

``

`794`

``

`-

// ...look, just pretend you forgot what you just read.

`

`795`

``

`-

// Stability concerns.

`

`796`

``

`-

unsafe { mem::transmute(self) }

`

``

`795`

`+

pub const fn to_bits(self) -> u16 {

`

``

`796`

`` +

// SAFETY: `u16` is a plain old datatype so we can always transmute to it.

``

``

`797`

`+

// ...sorta.

`

``

`798`

`+

//

`

``

`799`

`+

// It turns out that at runtime, it is possible for a floating point number

`

``

`800`

`+

// to be subject to a floating point mode that alters nonzero subnormal numbers

`

``

`801`

`+

// to zero on reads and writes, aka "denormals are zero" and "flush to zero".

`

``

`802`

`+

//

`

``

`803`

`+

// And, of course evaluating to a NaN value is fairly nondeterministic.

`

``

`804`

`+

// More precisely: when NaN should be returned is knowable, but which NaN?

`

``

`805`

`+

// So far that's defined by a combination of LLVM and the CPU, not Rust.

`

``

`806`

`+

// This function, however, allows observing the bitstring of a NaN,

`

``

`807`

`+

// thus introspection on CTFE.

`

``

`808`

`+

//

`

``

`809`

`+

// In order to preserve, at least for the moment, const-to-runtime equivalence,

`

``

`810`

`+

// we reject any of these possible situations from happening.

`

``

`811`

`+

#[inline]

`

``

`812`

`+

#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]

`

``

`813`

`+

const fn ct_f16_to_u16(ct: f16) -> u16 {

`

``

`814`

`` +

// FIXME(f16_f128): we should use `.classify()` like `f32` and `f64`, but we don't yet

``

``

`815`

`+

// want to rely on that on all platforms because it is nondeterministic (e.g. x86 has

`

``

`816`

`+

// convention discrepancies calling intrinsics). So just classify the bits instead.

`

``

`817`

`+`

``

`818`

`+

// SAFETY: this is a POD transmutation

`

``

`819`

`+

let bits = unsafe { mem::transmute::<f16, u16>(ct) };

`

``

`820`

`+

match f16::classify_bits(bits) {

`

``

`821`

`+

FpCategory::Nan => {

`

``

`822`

`+

panic!("const-eval error: cannot use f16::to_bits on a NaN")

`

``

`823`

`+

}

`

``

`824`

`+

FpCategory::Subnormal => {

`

``

`825`

`+

panic!("const-eval error: cannot use f16::to_bits on a subnormal number")

`

``

`826`

`+

}

`

``

`827`

`+

FpCategory::Infinite | FpCategory::Normal | FpCategory::Zero => bits,

`

``

`828`

`+

}

`

``

`829`

`+

}

`

``

`830`

`+`

``

`831`

`+

#[inline(always)] // See https://github.com/rust-lang/compiler-builtins/issues/491

`

``

`832`

`+

fn rt_f16_to_u16(x: f16) -> u16 {

`

``

`833`

`` +

// SAFETY: `u16` is a plain old datatype so we can always... uh...

``

``

`834`

`+

// ...look, just pretend you forgot what you just read.

`

``

`835`

`+

// Stability concerns.

`

``

`836`

`+

unsafe { mem::transmute(x) }

`

``

`837`

`+

}

`

``

`838`

`+

intrinsics::const_eval_select((self,), ct_f16_to_u16, rt_f16_to_u16)

`

`797`

`839`

`}

`

`798`

`840`

``

`799`

`841`

`` /// Raw transmutation from `u16`.

``

`@@ -837,11 +879,52 @@ impl f16 {

`

`837`

`879`

`#[inline]

`

`838`

`880`

`#[must_use]

`

`839`

`881`

`#[unstable(feature = "f16", issue = "116909")]

`

`840`

``

`-

pub fn from_bits(v: u16) -> Self {

`

`841`

``

`` -

// SAFETY: `u16` is a plain old datatype so we can always... uh...

``

`842`

``

`-

// ...look, just pretend you forgot what you just read.

`

`843`

``

`-

// Stability concerns.

`

`844`

``

`-

unsafe { mem::transmute(v) }

`

``

`882`

`+

#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]

`

``

`883`

`+

pub const fn from_bits(v: u16) -> Self {

`

``

`884`

`+

// It turns out the safety issues with sNaN were overblown! Hooray!

`

``

`885`

`` +

// SAFETY: `u16` is a plain old datatype so we can always transmute from it

``

``

`886`

`+

// ...sorta.

`

``

`887`

`+

//

`

``

`888`

`+

// It turns out that at runtime, it is possible for a floating point number

`

``

`889`

`+

// to be subject to floating point modes that alter nonzero subnormal numbers

`

``

`890`

`+

// to zero on reads and writes, aka "denormals are zero" and "flush to zero".

`

``

`891`

`+

// This is not a problem usually, but at least one tier2 platform for Rust

`

``

`892`

`+

// actually exhibits this behavior by default: thumbv7neon

`

``

`893`

`+

// aka "the Neon FPU in AArch32 state"

`

``

`894`

`+

//

`

``

`895`

`+

// And, of course evaluating to a NaN value is fairly nondeterministic.

`

``

`896`

`+

// More precisely: when NaN should be returned is knowable, but which NaN?

`

``

`897`

`+

// So far that's defined by a combination of LLVM and the CPU, not Rust.

`

``

`898`

`+

// This function, however, allows observing the bitstring of a NaN,

`

``

`899`

`+

// thus introspection on CTFE.

`

``

`900`

`+

//

`

``

`901`

`+

// In order to preserve, at least for the moment, const-to-runtime equivalence,

`

``

`902`

`+

// reject any of these possible situations from happening.

`

``

`903`

`+

#[inline]

`

``

`904`

`+

#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]

`

``

`905`

`+

const fn ct_u16_to_f16(ct: u16) -> f16 {

`

``

`906`

`+

match f16::classify_bits(ct) {

`

``

`907`

`+

FpCategory::Subnormal => {

`

``

`908`

`+

panic!("const-eval error: cannot use f16::from_bits on a subnormal number")

`

``

`909`

`+

}

`

``

`910`

`+

FpCategory::Nan => {

`

``

`911`

`+

panic!("const-eval error: cannot use f16::from_bits on NaN")

`

``

`912`

`+

}

`

``

`913`

`+

FpCategory::Infinite | FpCategory::Normal | FpCategory::Zero => {

`

``

`914`

`+

// SAFETY: It's not a frumious number

`

``

`915`

`+

unsafe { mem::transmute::<u16, f16>(ct) }

`

``

`916`

`+

}

`

``

`917`

`+

}

`

``

`918`

`+

}

`

``

`919`

`+`

``

`920`

`+

#[inline(always)] // See https://github.com/rust-lang/compiler-builtins/issues/491

`

``

`921`

`+

fn rt_u16_to_f16(x: u16) -> f16 {

`

``

`922`

`` +

// SAFETY: `u16` is a plain old datatype so we can always... uh...

``

``

`923`

`+

// ...look, just pretend you forgot what you just read.

`

``

`924`

`+

// Stability concerns.

`

``

`925`

`+

unsafe { mem::transmute(x) }

`

``

`926`

`+

}

`

``

`927`

`+

intrinsics::const_eval_select((v,), ct_u16_to_f16, rt_u16_to_f16)

`

`845`

`928`

`}

`

`846`

`929`

``

`847`

`930`

`/// Return the memory representation of this floating point number as a byte array in

`

`@@ -860,8 +943,9 @@ impl f16 {

`

`860`

`943`

```` /// ```

861

944

`#[inline]

`

862

945

`#[unstable(feature = "f16", issue = "116909")]

`

``

946

`+

#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]

`

863

947

`#[must_use = "this returns the result of the operation, without modifying the original"]

`

864

``

`-

pub fn to_be_bytes(self) -> [u8; 2] {

`

``

948

`+

pub const fn to_be_bytes(self) -> [u8; 2] {

`

865

949

`self.to_bits().to_be_bytes()

`

866

950

`}

`

867

951

``

`@@ -881,8 +965,9 @@ impl f16 {

`

881

965

```` /// ```


`882`

`966`

`#[inline]

`

`883`

`967`

`#[unstable(feature = "f16", issue = "116909")]

`

``

`968`

`+

#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]

`

`884`

`969`

`#[must_use = "this returns the result of the operation, without modifying the original"]

`

`885`

``

`-

pub fn to_le_bytes(self) -> [u8; 2] {

`

``

`970`

`+

pub const fn to_le_bytes(self) -> [u8; 2] {

`

`886`

`971`

`self.to_bits().to_le_bytes()

`

`887`

`972`

`}

`

`888`

`973`

``

`@@ -915,8 +1000,9 @@ impl f16 {

`

`915`

`1000`

```` /// ```

916

1001

`#[inline]

`

917

1002

`#[unstable(feature = "f16", issue = "116909")]

`

``

1003

`+

#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]

`

918

1004

`#[must_use = "this returns the result of the operation, without modifying the original"]

`

919

``

`-

pub fn to_ne_bytes(self) -> [u8; 2] {

`

``

1005

`+

pub const fn to_ne_bytes(self) -> [u8; 2] {

`

920

1006

`self.to_bits().to_ne_bytes()

`

921

1007

`}

`

922

1008

``

`@@ -938,7 +1024,8 @@ impl f16 {

`

938

1024

`#[inline]

`

939

1025

`#[must_use]

`

940

1026

`#[unstable(feature = "f16", issue = "116909")]

`

941

``

`-

pub fn from_be_bytes(bytes: [u8; 2]) -> Self {

`

``

1027

`+

#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]

`

``

1028

`+

pub const fn from_be_bytes(bytes: [u8; 2]) -> Self {

`

942

1029

`Self::from_bits(u16::from_be_bytes(bytes))

`

943

1030

`}

`

944

1031

``

`@@ -960,7 +1047,8 @@ impl f16 {

`

960

1047

`#[inline]

`

961

1048

`#[must_use]

`

962

1049

`#[unstable(feature = "f16", issue = "116909")]

`

963

``

`-

pub fn from_le_bytes(bytes: [u8; 2]) -> Self {

`

``

1050

`+

#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]

`

``

1051

`+

pub const fn from_le_bytes(bytes: [u8; 2]) -> Self {

`

964

1052

`Self::from_bits(u16::from_le_bytes(bytes))

`

965

1053

`}

`

966

1054

``

`@@ -993,7 +1081,8 @@ impl f16 {

`

993

1081

`#[inline]

`

994

1082

`#[must_use]

`

995

1083

`#[unstable(feature = "f16", issue = "116909")]

`

996

``

`-

pub fn from_ne_bytes(bytes: [u8; 2]) -> Self {

`

``

1084

`+

#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]

`

``

1085

`+

pub const fn from_ne_bytes(bytes: [u8; 2]) -> Self {

`

997

1086

`Self::from_bits(u16::from_ne_bytes(bytes))

`

998

1087

`}

`

999

1088

``