Skip to content

Tracking issue for release notes of #128596: stabilize const_fn_floating_point_arithmetic #129567

Closed

Description

@rustbot

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.

Activity

  1. added
    relnotesMarks issues that should be documented in the release notes of the next release.
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Aug 25, 2024
  2. added this to the 1.82.0 milestone on Aug 25, 2024
  3. added
    I-lang-nominatedNominated for discussion during a lang team meeting.
    WG-const-evalWorking group: Const evaluation
    and removed
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Aug 25, 2024
  4. traviscross commented on Aug 28, 2024

    @traviscross
    Contributor

    @RalfJung: What do you think?

    cc @rust-lang/lang

  5. RalfJung commented on Aug 28, 2024

    @RalfJung
    Member

    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.

  6. traviscross commented on Aug 28, 2024

    @traviscross
    Contributor

    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?

  7. RalfJung commented on Aug 28, 2024

    @RalfJung
    Member

    #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 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.

    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.

  8. traviscross commented on Aug 28, 2024

    @traviscross
    Contributor

    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.

  9. added
    T-langRelevant to the language team
    relnotesMarks 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.
    and removed
    relnotesMarks issues that should be documented in the release notes of the next release.
    I-lang-nominatedNominated for discussion during a lang team meeting.
    relnotes-tracking-issueMarks issues tracking what text to put in release notes.
    on Sep 24, 2024
  10. RalfJung commented on Oct 18, 2024

    @RalfJung
    Member

    The release is out... will the bot close all the issues at some point or what's the plan for that?

  11. cuviper commented on Oct 19, 2024

    @cuviper
    Member

    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...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    I-release-nominatedNominated for the release team.T-langRelevant to the language teamWG-const-evalWorking group: Const evaluationrelnotesMarks 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.

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions