Code change:
Tracking issue for the conversion feature, by PR . The main topic during the PR's thread has been about how to handle signaling NaNs, and the final decision was to silently mask them, especially as LLVM behaviour regarding them is not well specified. Another issue by was that sNaNs are not encoded consistently. IEEE 754-2008 (section 8.2.1 in the ) specifies quiet NaNs to have their first bit of the trailing significand field set to 1, for signaling NaNs it should be set to 0. Some MIPS based platforms have it reversed. Should they be cfg'd out?
Hmm, seems this feature has broken the crate: Apparently you can't shadow functions with a trait: (the first assert works, but the second fails)
Is the issue above something we have to fix, or rather something the crate has to?
RFC 1105 laid out that so it's up to the team(s) to decide whether we're okay with the practical impact of the change.
cc --- with this merged, could we get this feature stabilized in Rust 1.20?
has been submitted to stabilize this. fcp merge
Team member has proposed to merge this. The next step is review by the rest of the tagged teams: [x] [x] [x] [x] [x] [x] [x] No concerns currently listed. Once these reviewers reach consensus, this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See for info about what commands tagged team members can give me.
reviewed
:bell: This is now entering its final comment period, as per the . :bell:
:bell: This is now entering its final comment period, as per the . :bell:
The final comment period is now complete.
The final comment period is now complete.
Really late to this party. As I note , the NaN masking is unnecessary from LLVM's perspective. I'm not totally clear on the platform-specific-NaN-reprs issue, but at least on x86/x64, we can just make into transmute safely. (probably also aarch64? At least its SIMD units are IEEE 754-2008 compliant, which specs NaN repr). The documentation has been written sufficiently vaguely to allow us to change the implementation to a transmute. If we wish to do so, this just leaves the following question: do we ignore the existence of non-2008-compliant hardware (transmute on all platforms) or do we allow behaviour to be platform-specific (transmute only on definitely-2008-compliant hardware)?
I'm certainly on board with just transmuting on architectures we know are okay.
Transmuting should be safe on ARM & AArch64. The only issue is whether a sNaN can cause a trap when it is used. By default floating-point exception are masked on ARM/AArch64, but can be enabled by setting some bits in the / register. These bits also allow enabling exceptions for situations like inexact floating-point rounding, float division by zero, etc. These operations are all supported in safe Rust, so I suggest that the official Rust policy be something along the lines: "Rust assumes that all floating-point operations do not trap."
I don't think we really care if the operation traps, right? It's not unsafe to do so.
We do care if the trap is considered an "observable side-effect" of the operation, since this affects optimization. This would impact dead code elimination for example: you would still have to trigger the trap even if the result of the operation is not used.
Ah sure that makes sense.
very interesting! We need more people like you :). I am personally okay with anything (the documentation was made vague purposefully!), but before we commit to anything that we can't reverse (e.g. making docs super clear that it is only a transmute), I'd love to get 's LLVM patch merged upstream so that it has been reviewed by LLVM reviewers and deemed okay.
Unfortunately, it is still necessary from LLVM's perspective; see for example. I support changing LLVM's behavior here, but this isn't just a case of fixing mistaken documentation; it's changing the policy, so we need to be careful.
Interesting. That transformation is justified by sNaN being bad, but in fact doesn't look for sNaN. Rather it looks for undef, and up to this point we've fairly conservatively considered doing ~anything with undef to be UB for Rust (because undef is poorly defined and we don't want to couple with LLVM semantics anyway). As such, the existence of that transformation shouldn't actually be a barrier to us making this change? (we should still fix llvm as well)
FWIW, that change originally came from here:
That's a good point. Allowing Rust to produce sNaNs in more places doesn't break those kinds of optimizations. And I'm not aware of any optimizations that explicitly check for sNaNs, and I've checked all the usual suspects. So this change seems ok.
cc

Related discussion:
text: /// # Examples /// /// ``` <del> /// #![feature(float_bits_conv)] </del> /// assert!((1f64).to_bits() != 1f64 as u64); // to_bits() is not casting! /// assert_eq!((12.5f64).to_bits(), 0x4029000000000000); /// /// ``` <del> #[unstable(feature = "float_bits_conv", reason = "recently added", issue = "40470")] </del> <ins> #[stable(feature = "float_bits_conv", since = "1.21.0")] </ins> #[inline] pub fn to_bits(self) -> u64 { unsafe { ::mem::transmute(self) }