Rfcs: Idea: NonZero-like float wrappers

Created on 3 Jun 2018  Â·  6Comments  Â·  Source: rust-lang/rfcs

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.

T-libs

Most helpful comment

All 6 comments

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:

  1. Newtypes which impose some logical invariant on the wrapped type to rule out logically invalid or dubious states
  2. Restrictions on valid bit patterns to enable layout optimizations

I don't have super great rationale for that at the moment, but I can vaguely gesture at the following observations:

  • Logical newtypes (1) can have logic bugs and those may lead to a buggy overall program depending on the bug and how the newtype is used in the program, but for niches (2) even just producing an invalid bit pattern anywhere is instant UB.
  • At least the examples of (2) that we have today are often used in critical unsafe abstractions (because they allow making key data structures more compact) which are full of unsafe code anyway and don't want to pay for unnecessary safety checks. Thus there's a real need for unsafe constructors like 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.
  • Logical new types (1) may want to offer a quite extensive and opinionated API surface mirroring the underlying type's operations. In contrast, the "niche types" (2) we have so far have a very minimal API because they're just for storage. If you want to operate on a 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.

    • For floats in particular, one could (for example) imagine a NonNan type which provides the usual arithmetic operations and panics if a Nan is produced (analogous to integer overflow checking). Data structures storing floats that just want to provide niches probably don't want all that baggage.

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mqudsi picture mqudsi  Â·  3Comments

Diggsey picture Diggsey  Â·  3Comments

camden-smallwood-zz picture camden-smallwood-zz  Â·  3Comments

onelson picture onelson  Â·  3Comments

rust-highfive picture rust-highfive  Â·  4Comments