Repository navigation
floating point to integer casts can cause undefined behaviour #10184
Description
Status as of 2020-04-18
We intend to stabilize the saturating-float-casts behavior for as, and have stabilized unsafe library functions that handle the previous behavior. See #71269 for the latest discussion on that stabilization process.
Status as of 2018-11-05
A flag has been implemented in the compiler, -Zsaturating-float-casts, which will cause all float to integer casts have "saturating" behavior where if it's out of bounds it's clamped to the nearest bound. A call for benchmarking of this change went out awhile ago. Results, while positive in many projects, are quite negative for some projects and indicates that we're not done here.
The next steps are figuring out how to recover performance for these cases:
- One option is to take today's
ascast behavior (which is UB in some cases) and addunsafefunctions for the relevant types and such. - Another is to wait for LLVM to add a
freezeconcept which means that we get a garbage bit pattern, but it's at least not UB - Another is to implement casts via inline assembly in LLVM IR, as the current codegen is not heavily optimized.
Old status
UPDATE (by @nikomatsakis): After much discussion, we've got the rudiments of a plan for how to address this problem. But we need some help with actually investigating the performance impact and working out the final details!
ORIGINAL ISSUE FOLLOWS:
If the value cannot fit in ty2, the results are undefined.
1.04E+17 as u8
Activity
brson commentedon Oct 31, 2013
Nominating
pnkfelix commentedon Nov 7, 2013
accepted for P-high, same reasoning as #10183
pcwalton commentedon Nov 22, 2013
I don't think this is backwards incompatible at a language level. It will not cause code that was working OK to stop working. Nominating.
pnkfelix commentedon Dec 19, 2013
changing to P-high, same reasoning as #10183
nrc commentedon Sep 12, 2014
How do we propose to solve this and #10185? Since whether behaviour is defined or not depends on the dynamic value of the number being cast, it seems the only solution is to insert dynamic checks. We seem to agree we do not want to do that for arithmetic overflow, are we happy to do it for cast overflow?
pcwalton commentedon Sep 12, 2014
We could add an intrinsic to LLVM that performs a "safe conversion". @zwarich may have other ideas.
zwarich commentedon Sep 12, 2014
AFAIK the only solution at the moment is to use the target-specific intrinsics. That's what JavaScriptCore does, at least according to someone I asked.
pcwalton commentedon Sep 12, 2014
Oh, that's easy enough then.
nrc commentedon Apr 23, 2015
ping @pnkfelix is this covered by the new overflow checking stuff?
bluss commentedon May 7, 2015
These casts are not checked by rustc with debug assertions.
Aatch commentedon Sep 13, 2015
I'm happy to handle this, but I need a concrete solution. I personally think that it should be checked along with overflowing integer arithmetic, as it's a very similar issue. I don't really mind what we do though.
Note that this issue is currently causing an ICE when used in certain constant expressions.
bluss commentedon Sep 13, 2015
This allows violating memory safety in safe rust, example from this forum post:
steveklabnik commentedon Oct 8, 2015
Marking with I-unsound given the violation of memory safety in safe rust.
steveklabnik commentedon Oct 29, 2015
@bluss , this does not segfualt for me, just gives an assertion error. untagging since i was the one who added it
262 remaining items
federicomenaquintero commentedon Apr 22, 2020
Are there plans for checked conversions? Something like
fn i32::checked_from(f64) -> Result<i32, DoesntFit>?kennytm commentedon Apr 22, 2020
You'll need to consider what should
i32::checked_from(4.5)return.Rollup merge of rust-lang#71269 - Mark-Simulacrum:sat-float-casts, r=…
Rollup merge of rust-lang#71269 - Mark-Simulacrum:sat-float-casts, r=…
Panic if NaN is passed to `Duration` constructors
Auto merge of rust-lang#10184 - robertbastian:master, r=xFrednet
Rely on defined saturation behavior for f32 to u8 casts
Rely on defined saturation behavior for f32 to u8 casts (#87)
Add clamp function due to rust-lang/rust#10184
Merge rust-lang#10188