Repository navigation
Tracking issue for release notes of #128596: stabilize const_fn_floating_point_arithmetic #129567
Copy link
Copy link
Closed
Labels
I-release-nominatedNominated for the release team.Nominated for the release team.T-langRelevant to the language teamRelevant to the language teamWG-const-evalWorking group: Const evaluationWorking group: Const evaluationrelnotesMarks issues that should be documented in the release notes of the next release.Marks issues that should be documented in the release notes of the next release.relnotes-tracking-issueMarks issues tracking what text to put in release notes.Marks issues tracking what text to put in release notes.
Milestone
Description
This issue tracks the release notes text for #128596.
- Issue is nominated for the responsible team (and T-release nomination is removed).
- Proposed text is drafted by team responsible for underlying change.
- Issue is nominated for release team review of clarity for wider audience.
- Release team includes text in release notes/blog posts.
Release notes text:
The section title will be de-duplicated by the release team with other release notes issues.
Prefer to use the standard titles from previous releases.
More than one section can be included if needed.
# Language
- [Stabilize floating-point arithmetic in `const fn`](https://github.com/rust-lang/rust/pull/128596)Release blog section (if any, leave blank if no section is expected):
### Resolving the semantics of NaN-producing floating-point operations
Operations on floating-point values (of type `f32` and `f64`) are famously subtle. One of the reasons for this is the existence of "NaN values": this is short for "Not a Number", and is used to represent e.g. the result of `0.0 / 0.0`. What makes NaN values subtle is that more than one possible NaN value exists: a NaN value has a sign that can be checked with `f.is_sign_positive()`, and it has a "payload" that can be extracted with `f.to_bits()`. Despite very successful efforts to standardize the behavior of floating-point operations across hardware architectures, the details of when a NaN is positive or negative and what its exact payload is differ across architectures. To make matters even more complicated, Rust and its LLVM backend apply optimizations to floating-point operations when the exact numeric result is guaranteed not to change, but those optimizations can change which NaN value is produced. For instance, `f * 1.0` may be optimized to just `f`. However, if `f` is a NaN, this can change the exact bit pattern of the result!
With this release, Rust standardizes on a set of rules for how NaN values behave. This set of rules is *not* fully deterministic, which means that the result of operations like `(0.0 / 0.0).is_sign_positive()` can differ depending on the hardware architecture, optimization levels, and the surrounding code. Code that aims to be fully portable should avoid using `to_bits` and should use `f.signum() == 1.0` instead of `f.is_sign_positive()`. However, the rules are carefully chosen to still allow advanced optimization techniques such as NaN boxing to be realized in Rust code. For more details on what the exact rules are, check out our [documentation](https://doc.rust-lang.org/std/primitive.f32.html#nan-bit-patterns).
With the semantics for NaN values settled, this release also permits the use of floating-point operations in `const fn`. Due to the reasons described above, operations like `(0.0 / 0.0).is_sign_positive()` can produce a different result when executed at compile-time vs at run-time; this is not a bug and code must not rely on a `const fn` always producing the exact same result.Metadata
Metadata
Assignees
Labels
I-release-nominatedNominated for the release team.Nominated for the release team.T-langRelevant to the language teamRelevant to the language teamWG-const-evalWorking group: Const evaluationWorking group: Const evaluationrelnotesMarks issues that should be documented in the release notes of the next release.Marks issues that should be documented in the release notes of the next release.relnotes-tracking-issueMarks issues tracking what text to put in release notes.Marks issues tracking what text to put in release notes.
Activity
traviscross commentedon Aug 28, 2024
@RalfJung: What do you think?
cc @rust-lang/lang
RalfJung commentedon Aug 28, 2024
Who decides whether there'll be a release blog section? I don't know yet whether I will have time to draft one, but if I do I'd rather not see that effort wasted.
traviscross commentedon Aug 28, 2024
I would assume that T-release would take a cue from e.g. lang about what's important enough to mention. This one seems it would be. But there will actually be quite a bit worth mentioning in Rust 1.82. Not sure if we have a word count limit.
@rust-lang/release: What do you think about RalfJ's question?
RalfJung commentedon Aug 28, 2024
#129559 will also be in 1.82, so there could be a joint relnotes section on float semantics. Cc @beetrees @tgross35
Resolving the semantics of NaN-producing floating-point operations
Operations on floating-point values (of type
f32andf64) are famously subtle. One of the reasons for this is the existence of "NaN values": this is short for "Not a Number", and is used to represent e.g. the result of0.0 / 0.0. What makes NaN values subtle is that more than one possible NaN value exists: a NaN value has a sign that can be checked withf.is_sign_positive(), and it has a "payload" that can be extracted withf.to_bits(). Despite very successful efforts to standardize the behavior of floating-point operations across hardware architectures, the details of when a NaN is positive or negative and what its exact payload is differ across architectures. To make matters even more complicated, Rust and its LLVM backend apply optimizations to floating-point operations when the exact numeric result is guaranteed not to change, but those optimizations can change which NaN value is produced. For instance,f * 1.0may be optimized to justf. However, iffis a NaN, this can change the exact bit pattern of the result!With this release, Rust standardizes on a set of rules for how NaN values behave. This set of rules is not fully deterministic, which means that the result of operations like
(0.0 / 0.0).is_sign_positive()can differ depending on the hardware architecture, optimization levels, and the surrounding code. Code that aims to be fully portable should avoid usingto_bitsand should usef.signum() == 1.0instead off.is_sign_positive(). However, the rules are carefully chosen to still allow advanced optimization techniques such as NaN boxing to be realized in Rust code. For more details on what the exact rules are, check out our documentation.With the semantics for NaN values settled, this release also permits the use of floating-point operations in
const fn. Due to the reasons described above, operations like(0.0 / 0.0).is_sign_positive()can produce a different result when executed at compile-time vs at run-time; this is not a bug and code must not rely on aconst fnalways producing the exact same result.traviscross commentedon Aug 28, 2024
This sounds great and hits the right mark in terms of giving background and broadly useful information that it'd be good for all Rust programmers to know.
RalfJung commentedon Oct 18, 2024
The release is out... will the bot close all the issues at some point or what's the plan for that?
cuviper commentedon Oct 19, 2024
If a bot hasn't done it already, I won't hold my breath for it. Let me see if I can mass close them...