Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upCasting u128::MAX to f32 is undefined #41799
Comments
est31
changed the title
i128 casting issue
i128 casting issue on debug
May 7, 2017
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
|
If it is currently UB then maybe #10185 needs to be reopened. |
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
ghost
commented
May 7, 2017
|
Yes, because the maximum value of a u64 fits in a f32 fine. |
nagisa
referenced this issue
May 8, 2017
Closed
integer to floating point casts can cause undefined behaviour #10185
nagisa
changed the title
i128 casting issue on debug
Casting i128 to f32 is undefined
May 8, 2017
nagisa
added
I-wrong
T-compiler
labels
May 8, 2017
nagisa
changed the title
Casting i128 to f32 is undefined
Casting u128::MAX to f32 is undefined
May 8, 2017
nagisa
referenced this issue
May 8, 2017
Closed
Tracking issue for 128-bit integer support (RFC 1504) #35118
nagisa
added
the
T-lang
label
May 8, 2017
This comment has been minimized.
This comment has been minimized.
|
Cross-linking #10184. |
This comment has been minimized.
This comment has been minimized.
|
Don't forget #15536. |
This comment has been minimized.
This comment has been minimized.
isislovecruft
commented
May 8, 2017
|
Hi! Sorry if this is a stupid suggestion… but as someone who uses u128 (in several cryptographic libraries) and doesn't use floats, I wonder how many |
This comment has been minimized.
This comment has been minimized.
|
If a new |
This comment has been minimized.
This comment has been minimized.
|
@isislovecruft Rust is a general purpose programming language and it already has a syntax for doing conversions that one could expect to work on all the primitive types, so it not supporting Furthermore, consider a code like this:
Now this macro works just fine for every single integer and float combo. Forbidding it for i/u128 would extend the discrepancy to macros as well. I hope that’s enough of demonstration of a need to keep functionality consistent. |
This comment has been minimized.
This comment has been minimized.
isislovecruft
commented
May 15, 2017
|
@nagisa The consistency issue, esp. w.r.t. macros, makes perfect sense. Thanks for taking the time to point that out. |
This comment has been minimized.
This comment has been minimized.
|
%1 = uitofp i128 %0 to floatwhich, on x86_64, i686 and aarch64, becomes a call to the compiler_rt function call __floatuntisf@PLTDirectly calling the function, instead of generating the The current implementation casts |
This comment has been minimized.
This comment has been minimized.
|
It makes no sense to do that over just adding the relevant branches into the IR, because it inhibits pretty much every optimisation with the values involved. |
This comment has been minimized.
This comment has been minimized.
|
@nagisa Yes we could do this if a >= 0xffffff80000000000000000000000000_u128 {
f32::INFINITY
} else {
a as f32
}producing %1 = icmp ugt i128 %0, -10141204801825835211973625643009
%2 = uitofp i128 %0 to float
%_0.0 = select i1 %1, float 0x7FF0000000000000, float %2producing (unfortunately the function will always be called, and the cold branch check remains) mov rbx, rsi
shr rbx, 39
call __floatuntisf@PLT
cmp rbx, 33554430 ; 0x1fffffe
jbe .LBB0_2
movss xmm0, dword ptr [rip + .LCPI0_0]
.LBB0_2:
ret
.LCPI0_0:
.long 2139095040 ; 0x7f800000 |
This comment has been minimized.
This comment has been minimized.
|
Or just add a lint/error if |
This comment has been minimized.
This comment has been minimized.
LLVM will want some solution that’s more general and we want to avoid having custom patches in our LLVM, so I do not think that would work.
Interesting option, but does not help with code like target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define internal i128 @foo() unnamed_addr {
start:
ret i128 -1
}
define float @bar() unnamed_addr {
start:
%0 = call i128 @foo()
%1 = uitofp i128 %0 to float
ret float %1
}which is still very UB, even if it does not produce a literal |
This comment has been minimized.
This comment has been minimized.
|
Ignoring LLVM and C/C++ for the moment, IEEE 754 section 5.4.1 "Arithmetic operations" defines
Integer to floating-point conversions typically use "to nearest" rounding. IEEE 754 section 4.3.1 "Rounding-direction attributes to nearest" defines "no nearest" and says:
|
bstrie
added
I-unsound 💥
I-nominated
labels
Jul 26, 2017
Mark-Simulacrum
added
C-bug
and removed
I-wrong
labels
Jul 27, 2017
aturon
added
P-medium
and removed
I-nominated
labels
Aug 3, 2017
This comment has been minimized.
This comment has been minimized.
|
Marking P-medium to match other similar bugs. |
alexcrichton
added a commit
to alexcrichton/rust
that referenced
this issue
Sep 2, 2017
alexcrichton
added a commit
to alexcrichton/rust
that referenced
this issue
Sep 2, 2017
bors
added a commit
that referenced
this issue
Sep 3, 2017
bors
added a commit
that referenced
this issue
Sep 3, 2017
bstrie
referenced this issue
Sep 17, 2017
Open
borrowed referent of a `&T` sometimes incorrectly allowed #38899
newpavlov
referenced this issue
Sep 18, 2017
Closed
RFC: new `rand-core` crate, `rand` adaptations #2152
bstrie
added
the
B-unstable
label
Sep 20, 2017
rkruppe
referenced this issue
Oct 11, 2017
Merged
Saturating casts between integers and floats #45205
bors
added a commit
that referenced
this issue
Oct 18, 2017
bors
added a commit
that referenced
this issue
Nov 7, 2017
bors
added a commit
that referenced
this issue
Nov 8, 2017
This comment has been minimized.
This comment has been minimized.
|
#45205 has been merged, so there's now an opt-in solution to this issue ( |
This comment has been minimized.
This comment has been minimized.
|
@rkruppe I'd say we should do a public call, asking people to test the feature and report back. Then if there are no major issues after idk, 2-3 weeks (some people only read the weekly newsletter), we could flip the defaults and allow an opt out. It could stay this way on the nightly channel and if there continue to be no issues, we can let it ride the trains and include it in the next beta to be added to the next stable (without an opt out, as it would require a -C option and you won't be able to remove the opt-out again). If we hear about issues while the feature is in the beta channel, we can disable it on the beta channel as well. |
This comment has been minimized.
This comment has been minimized.
|
@est31 Huh, that's a bit more scrutiny than I would have expected. To be clear, in the context of this issue I am only talking about u128 -> f32 casts, the float -> int direction covered by #10184 can and should be rolled out independently. With that in mind, do you think the change to u128 -> f32 casts is more likely to cause regressions than the average bug fix? |
rkruppe
added a commit
to rkruppe/rust
that referenced
this issue
Nov 9, 2017
rkruppe
referenced this issue
Nov 9, 2017
Merged
Make saturating u128 -> f32 casts the default behavior #45900
This comment has been minimized.
This comment has been minimized.
|
I've file a PR (#45900) to just make the u128->f32 behavior the default, refocusing the -Z flag to just cover float->int casts. As with any other change, we'll have up to six weeks in nightly and six weeks of beta to find and fix any regressions there may be. |
rkruppe
added a commit
to rkruppe/rust
that referenced
this issue
Nov 9, 2017
rkruppe
added a commit
to rkruppe/rust
that referenced
this issue
Nov 10, 2017
rkruppe
added a commit
to rkruppe/rust
that referenced
this issue
Nov 10, 2017
bors
added a commit
that referenced
this issue
Nov 12, 2017
bors
closed this
in
#45900
Nov 12, 2017
This comment has been minimized.
This comment has been minimized.
|
FYI overflowing s/uitofp casts are no longer considered undefined as of https://reviews.llvm.org/D47807. So we should be able to drop the extra range checking code somewhere in the future. |
est31 commentedMay 7, 2017
•
edited
Given this code (playpen):
It should print
Ok(2742605). In release mode, that happens, but in debug mode, it printsErr("Overflow").The value is mostly irrelevant, it would also work for
42.0.cc @nagisa
cc #35118 tracking issue