Code change:
First discussed in issue As of Rust 1.39, casting a floating point number to an integer with is Undefined Behavior if the value is out of range. fixes this soundness hole by making “saturate” to the maximum or minimum value of the integer type (or zero for ), but has measurable negative performance impact in some benchmarks. There is some consensus in that thread for enabling saturation by default anyway, but provide an alternative for users who know through some other mean that their values are in range. PR adds that method to each of and . /// #![feature(floatapproxuncheckedto)] /// /// let value = 4.6f32; /// let rounded = unsafe { value.approxuncheckedto::<u16() }; /// asserteq!(rounded, 4); /// /// let value = -128.9f32; /// let rounded = unsafe { value.approxuncheckedto::<i8() }; /// assert_eq!(rounded, std::i8::MIN); /// The trait (tracking issue: ) has macro-generated s for all combinations of primitive integer and primitive floating point types:
We briefly discussed this in the lang team meeting today, and felt that stabilizing this would help unblock progress on making not unsound in the edge cases (i.e., where this function is UB). would you be up for proposing FCP merge here to stabilize the methods (but not the backing trait)?
I have some concerns regarding the naming of these methods. First of all, the general convention in all existing methods is to put at the end of the name. The only exception to this rule is . Secondly, I feel that is a poor description of what is happening. This is particularly concerning since this is an unsafe function. I propose that these methods be renamed to , which makes it absolutely clear what operation is being performed. Since the current lang team consensus is to make perform a saturating conversion by default, the name also serves as a contrast to the "default" way of casting a float to an integer.
I plan to post a PR soon with the renaming to , possibly including a stabilization with that (since we often rename and stabilize in one go I think and it seems unlikely that waiting would help).
Proposing to merge this with the name . fcp merge
Team member has proposed to merge this. The next step is review by the rest of the tagged team members: [x] [ ] [x] [x] [x] [ ] No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), 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.
Renaming sounds fine. I’d just like to point out that we may want multiple float-to-int conversion methods (with different semantics) in the future:
:bell: This is now entering its final comment period, as per the . :bell:
I've opened up a PR with the rename and stabilization:
In Rust we have arithmetic operations that are checked in debug builds and unchecked in release builds. I think I'd like a FP-int conversion that does the same. Is this a good idea?
This has been discussed at length in An important difference is that unchecked arithmetic can let overflow happen which could could logic bugs, but the uncheked float to int conversion can causes Undefined Behavior which should never happen in Rust without .
Even if we take "unchecked in release mode" to mean "some defined behavior" rather than UB, the trade-offs are very different: With integer overflow, the "unchecked" option is defined as two's complement wrap-around, which is practically free to implement (just omit the overflow checks). For float-int casts, there is no behavior that's consistent across platforms and requires no extra code to be executed. Integer arithmetic is pervasive in most/all applications, so overflow checks apply in a ton of places and their performance impact can be spread across the whole application, requiring a "bulk" switch. In contrast, conversions from floats to integers are much rarer and (as far as we know) if saturation does impact performance then it's due to individual conversions in hot loops. This makes it much more practical and appealing to decide checked vs unchecked on a case-by-case basis after profiling and manual inspection.
The final comment period, with a disposition to merge, as per the , is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. The RFC will be merged soon.

Related discussion:
text: /// assuming that the value is finite and fits in that type. /// /// ``` <del> /// #![feature(float_approx_unchecked_to)] /// </del> /// let value = 4.6_f32; <del> /// let rounded = unsafe { value.approx_unchecked_to::<u16>() }; </del> <ins> /// let rounded = unsafe { value.to_int_unchecked::<u16>() }; </ins> /// assert_eq!(rounded, 4); /// /// let value = -128.9_f32; <del> /// let rounded = unsafe { value.approx_unchecked_to::<i8>() }; </del> <ins> /// let rounded = unsafe { value.to_int_unchecked::<i8>() }; </ins> /// assert_eq!(rounded, std::i8::MIN); /// ``` ///