Basically, the types NonNanF32/64 and FiniteF32/64. The main reasoning of having these in the standard library is to allow niche optimisations.
Additionally, both of these types could implement Ord as NaN wouldn't be valid for either.
I definitely think this would be a good idea!
See also:
Could we wait for a more general system based on const generics?
Isn't that kind of an Ouroboros - we want to use const generics to exclude NaN from floats but we can't use floats in const generics because of NaN?
@glaebhoerl Such a system would likely need to use integer ranges of the bitwise representation anyway, to properly express what they need to do.
I'd like NonNanF32/64 soon, because they can be Ord, and that could give a nice efficient type-based solution to the "why can't I sort my slice of f32s?" question.
I'm not sure that the Finite ones need the layout optimizations, especially not urgently, since there's so much NaN space compared to the only two infinities, and ±∞ aren't a problem for Ord/Eq. (And, more vagely, I'm not sure what code is totally fine with 1.8e308 but can’t handle +∞.)
My gut feeling is that we shouldn't necessarily mix up these two things:
I don't have super great rationale for that at the moment, but I can vaguely gesture at the following observations:
NonNull::new_unchecked there. In contrast, it seems to me that most use cases of (1) – which should be a roughly representative sample of all Rust programs out there – can probably afford the cost of validation and so (like most code) should prefer panics to UB as consequence of programmer errors.NonNull or NonZeroU32, you're supposed to extract the actual *mut T/u32 value, operate on it as usual, and if necessary wrap the result in the niche type again.It seems the underlying theme to what I'm saying is something like: the ideal "this bit pattern can never occur, if it does it's UB" API might look rather different from the ideal "i want to make sure to rule out this invalid value, if i mess up give me a nice error" API.
So I'd recommend that we make progress on the general (const generics, bit pattern range based) niche system @eddyb mentioned for providing layout optimizations. Independently, people can continue1 to experiment with APIs for logically-never-NaN newtypes, and when the aforementioned general niche system stabilizes, some of those library types can choose to use it to provide niches in addition to their logical invariants.
1 There's a lot of work in this area already. A quick search for "ord float" on crates.io gives: ordered-float, float-ord, float, decorum, ord_subset, new-ordered-float, noisy_float, and fin. I've not looked at how all of those work but they all claim to address the problem of sorting a collection of floats in some way.
Most helpful comment
I definitely think this would be a good idea!
See also:
https://github.com/rust-lang/rfcs/issues/1249
https://internals.rust-lang.org/t/pre-pre-rfc-range-restricting-wrappers-for-floating-point-types/6701