-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make float::from_bits transmute #46012
Conversation
r? @sfackler |
It's possible this is also valid on powerpc/sparc64/asmjs but I'm keeping this down to the platforms where I know this works and I actually care about them. :) |
I'm definitely on board with this, but I think we should get everyone's eyes on it. @rfcbot fcp merge |
Team member @sfackler has proposed to merge this. The next step is review by the rest of the tagged teams: 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 this document for info about what commands tagged team members can give me. |
This is the mirror commit to rust-lang/rust#46012
src/libstd/f32.rs
Outdated
// The check above only assumes IEEE 754-1985 to be | ||
// valid. | ||
v = unsafe { ::mem::transmute(NAN) }; | ||
if cfg!(not(any( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add comments here and below noting why we only do this on some platforms?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The existing comment seems to address it, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The existing comment just says why we reset to a "canonical" NaN instead of just masking off the signal bit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"While IEEE 754-2008 specifies encodings for quiet NaNs and signaling ones, certain MIPS and PA-RISC CPUs treat signaling NaNs differently."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Err wait, I think I don't follow what you're asking/saying?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation to this function states that "due to the implications of Rust's safety promises being uncertain, if the representation of a signaling NaN "sNaN" float is passed to the function, the implementation is allowed to return a quiet NaN instead".
Someone looking at the implementation may wonder why those questions about safety promises are not a problem on these four architectures, but are on others. There should be a comment saying why this adjustment isn't needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would instead suggest changing the documentation to be "due to some platforms not conforming to IEEE 758-2008..."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand what IEEE 758-2008 compliance has to do with LLVM treating sNaN as UB or not.
1154b87
to
8d3e910
Compare
I have changed the PR to transmute on all platforms. The platform-specific cfg was based on me getting confused as a result of the implementation, documentation, and example all being inconsistent with eachother. See commit message for details. |
This is the mirror commit to rust-lang/rust#46012
This is the mirror commit to rust-lang/rust#46012
Should the weasel words around sNaN be removed, i.e., should we commit to not masking sNaN? And if so, should the the docs also include the note about non-IEEE platforms that's in the commit, to warn people against using it for platform-independent de-/serialization? |
8d3e910
to
8852757
Compare
Note that the platforms in question are IEEE 758-1985 compliant. It's just how to interpret the signaling bit wasn't spec'd until the 2008 version. Upon reflection, this implementation is maximally good at network interop if you're doing NaN-boxing that just slurps up the mantissa bits. It's not as good if you're specifically just caring about whether the NaN signals or not. The alternative would be to preserve signaling-ness, at the cost of clobbering the signaling bit across platforms. On balance my submitted implementation seems the most useful, and if the alternative behaviour is desired, then it should be a seperate function (since this behaviour is still desirable). In practice, I expect no one will notice or care. |
I think the guarantees we want to document are that:
Does that seem right? |
8852757
to
6f2cf4e
Compare
That is a reasonably minimal specification that I would be happy with, yes. (pushed test changes) |
I think we also want to guarantee this, right? |
6f2cf4e
to
3bc8a61
Compare
@gankro Thanks for all the leg work on this. :-) I admit, I still feel a little squishy over this, but folks with more experience than me on these matters seem quite confident, so I'm content to move forward. |
I think the docs may want to be updated here as well, but could we perhaps word them in such a way that implies that despite the current behavior we may change things in the future if necessary? (in that do we really trust LLVM to never change in this regard?) |
Willing to change docs if desired (though they are still technically correct), but I'd like to get sign off from the rest of the libs team before digging into that. (the impl should be ~independent) |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
We discussed this at the last libs meeting and decided that the guarantees in #46012 (comment) seem reasonable. |
3bc8a61
to
5e47285
Compare
After some discussion on IRC, it seems like it would be better to simply state "it's just transmute", and explain the implications of this. This ends up providing basically the same guarantees as the libs team agreed to (except guaranteeing that cross-platform transfer is in fact bit-exact). Pushed updated docs. |
src/libstd/f32.rs
Outdated
/// to interpret the NaN signaling bit wasn't actually specified. Most platforms | ||
/// (notably x86 and ARM) picked the interpretation that was ultimately | ||
/// standardized in 2008, but some didn't (notably MIPS). As a result, all | ||
/// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this really the case, or is it that the signalingness is selected by some payload bit in the other encoding?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They literally agree on the bit, but one says 1=signaling, and the other says 0=signaling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, lol
Build's red, but r=me otherwise. |
…ect this). The current implementation/documentation was made to avoid sNaN because of potential safety issues implied by old/bad LLVM documentation. These issues aren't real, so we can just make the implementation transmute (as permitted by the existing documentation of this method). Also the documentation didn't actually match the behaviour: it said we may change sNaNs, but in fact we canonicalized *all* NaNs. Also an example in the documentation was wrong: it said we *always* change sNaNs, when the documentation was explicitly written to indicate it was implementation-defined. This makes to_bits and from_bits perfectly roundtrip cross-platform, except for one caveat: although the 2008 edition of IEEE-754 specifies how to interpet the signaling bit, earlier editions didn't. This lead to some platforms picking the opposite interpretation, so all signaling NaNs on x86/ARM are quiet on MIPS, and vice-versa. NaN-boxing is a fairly important optimization, while we don't even guarantee that float operations properly preserve signalingness. As such, this seems like the more natural strategy to take (as opposed to trying to mangle the signaling bit on a per-platform basis). This implementation is also, of course, faster.
5e47285
to
439576f
Compare
Fixed? (tidy whitespace) |
@bors r+ |
📌 Commit 439576f has been approved by |
This is the mirror commit to rust-lang/rust#46012
Make float::from_bits transmute See commit message for details. See also this discussion here: #40470 (comment) (may require libs team discussion before merging)
@bors retry The AppVeyor
|
Make float::from_bits transmute See commit message for details. See also this discussion here: #40470 (comment) (may require libs team discussion before merging)
☀️ Test successful - status-appveyor, status-travis |
The Curse Is Lifted |
This is the mirror commit to rust-lang/rust#46012
See commit message for details.
See also this discussion here: #40470 (comment)
(may require libs team discussion before merging)