Files
swift-mirror/stdlib
Xiaodi Wu c2ce1e4cc3 [stdlib] Restore NaN printing behavior that matches documented guarantees (#89579)
Since Swift 4.x, NaN printing behavior has drifted from version to
version. But we actually have documented guarantees about how it should
behave.

From `CustomStringConvertible`:
> If the passed instance conforms to `CustomStringConvertible`, the
`String(describing:)` initializer and the `print(_:)` function use the
instance’s custom `description` property.

From `description` on `Double` (or `Float`, etc.):
> For any NaN value, the property’s value is “nan”

As of recent versions of Swift, this is not so for stdlib floating-point
types: `print(-Float.nan)` outputs the _debug_ description instead of
the non-debug description. These two string representations are
distinguishable because `debugDescription` shows the sign (and, if
nonzero, the payload) of NaN.

---

The underlying implementation-level issue is that stdlib floating-point
types were made to conform to `TextOutputStreamable` as part of string
interpolation work for performance reasons. That implementation elected
to use debugging output, but (afaict) that decision does not seem to
have been based on a deliberate choice specifically to change the
behavior of NaN interpolation. Prior to that change, streaming and
interpolation used the non-debug description for stdlib floating-point
types (verified with Swift 4.x using SwiftFiddle).

(It seems an unstated invariant of `TextOutputStreamable` assumed by
various bits of the stdlib—including the quoted documentation above
since `TextOutputStreamable` conformance "trumps"
`CustomStringConvertible` conformance when it comes to printing—is that
what's written to the stream matches `description`.)

Therefore, this PR adds an explicit code path to
`TextOutputStreamable.write` to restore `"nan"` as the printed,
interpolated, and streamed output for floating-point NaN. This parallels
the existing explicit code path for `description` itself.

Additional testing is added to prevent this behavior from silently
drifting again from documented guarantees. (It's telling that getting CI
to pass on all platforms required no changes to any existing test.)

Resolves #89496 

<!--
If this pull request is targeting a release branch, please fill out the
following form:

https://github.com/swiftlang/.github/blob/main/PULL_REQUEST_TEMPLATE/release.md?plain=1

Otherwise, replace this comment with a description of your changes and
rationale. Provide links to external references/discussions if
appropriate.
If this pull request resolves any GitHub issues, link them like so:

  Resolves <link to issue>, resolves <link to another issue>.

For more information about linking a pull request to an issue, see:

https://docs.github.com/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue
-->

<!--
Before merging this pull request, you must run the Swift continuous
integration tests.
For information about triggering CI builds via @swift-ci, see:

https://github.com/apple/swift/blob/main/docs/ContinuousIntegration.md#swift-ci

Thank you for your contribution to Swift!
-->
2026-06-01 11:10:09 -04:00
..