- **Explanation**:
Implementation of an async catching initializer for Result as part of
https://github.com/swiftlang/swift-evolution/pull/3234
- **Scope**:
Details in proposal.
- **Issues**:
- **Original PRs**:
- **Risk**:
- **Testing**:
I've added two tests to cover some of functionality that was being
exercised for the synchronous cases. It seems sufficient to me, but I'd
like feedback on this.
- **Reviewers**:
Would love for @ktoso to have a peek before finalizing.
---------
Co-authored-by: Jamie <2119834+jamieQ@users.noreply.github.com>
Co-authored-by: Konrad `ktoso` Malawski <konrad.malawski@project13.pl>
Co-authored-by: Ben Rimmington <me@benrimmington.com>
Co-authored-by: Konrad Malawski <ktoso@apple.com>
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!
-->
Faster FP printing + Float80
**Explanation**: Implements a new, faster debugDescription for floating-point types that uses a modified form of Rafaello Giulietti's Schubfach algorithm. Also expands the Swift-based printing and parsing routines to fully support Float80.
**Scope**: The new routines provide exactly the same API and behavior as the previous floating-point printing and parsing. The addition of Float80 parsing support insulates us from OS-specific variations in strtold support.
**Risk**: Modest. The code has been well-tested, but there has been a history of 32-bit issues with previous work in this area.
**Testing**: Existing unit tests all pass, including tests that verify that we're exporting the same internal endpoints. In addition, correctness has been verified with an offline test suite.
Notes:
* The core _Float64ToASCII function is about 1/2 the code+data of the previous implementation and also nearly 2x faster than before. This means that Double.debugDescription now spends most of its time allocating memory for the returned String.
* The Float80 support for printing and parsing has enough extra precision to also support Float128 if we ever want to add that.
An off-by-one led to a rounding decision based on the
word just before the work buffer. This would randomly fail
depending on the contents of that word.
Fixes the bug and adds some more ties-round-even tests
to ensure coverage of all branches in this section.
There's a longstanding problem in implementing `-isEqualToString:`,
where if you don't know how to get fast access to the other NSString's
contents, you have to pick between doing it character by character (very
slow), or calling [other isEqualToString: self], which risks infinite
recursion if the other string does the same.
This cuts the gordian knot by adding a new method
`isEqualToBytes:encoding:count:`, so you can get the contents out of
`self`, and hand it to the other string, confident that it will not need
to (nor, in fact be able to) ask you anything that might recurse.