Add a new -ignore-spi-group-new-api flag that selectively suppresses
"new API without '@available'" diagnostics for specified SPI groups
while still reporting ABI-breaking changes.
rdar://167702700
Replace the use of rethrows and #isolation in
withTaskCancellationHandler with typed throws and
nonisolated(nonsending), respectively.
Fixes rdar://146901428.
Now accepted as
[SE-0489](https://github.com/ZevEisenberg/swift-evolution/blob/main/proposals/0489-codable-error-printing.md).
# To Do
- [x] confirm which version of Swift to use for the availability
annotations. Probably 6.3 at time of writing.
# Context
Re: [Swift forum
post](https://forums.swift.org/t/the-future-of-serialization-deserialization-apis/78585/77),
where a discussion about future serialization tools in Swift prompted
Kevin Perry to suggest that some proposed changes could actually be made
in today's stdlib.
# Summary of Changes
Conforms `EncodingError` and `DecodingError` to
`CustomDebugStringConvertible` and adds a more-readable
`debugDescription`.
# Future Directions
This is a pared-down version of some experiments I did in
[UsefulDecode](https://github.com/ZevEisenberg/UsefulDecode). The
changes in this PR are the best I could do without changing the public
interface of `DecodingError` and `EncodingError`, and without modifying
the way the `JSON`/`PropertyList` `Encoder`/`Decoder` in Foundation
generate their errors' debug descriptions.
In the above-linked
[UsefulDecode](https://github.com/ZevEisenberg/UsefulDecode) repo, when
JSON decoding fails, I go back and re-decode the JSON using
`JSONSerialization` in order to provide more context about what failed,
and why. I didn't attempt to make such a change here, but I'd like to
discuss what may be possible.
# Examples
To illustrate the effect of the changes in this PR, I removed my changes
to stdlib/public/core/Codable.swift and ran my new test cases again.
Here are the resulting diffs.
##
`test_encodingError_invalidValue_nonEmptyCodingPath_nilUnderlyingError`
### Before
`invalidValue(234, Swift.EncodingError.Context(codingPath:
[GenericCodingKey(stringValue: "first", intValue: nil),
GenericCodingKey(stringValue: "second", intValue: nil),
GenericCodingKey(stringValue: "2", intValue: 2)], debugDescription: "You
cannot do that!", underlyingError: nil))`
### After
`EncodingError.invalidValue: 234 (Int). Path: first.second[2]. Debug
description: You cannot do that!`
## `test_decodingError_valueNotFound_nilUnderlyingError`
### Before
`valueNotFound(Swift.String, Swift.DecodingError.Context(codingPath:
[GenericCodingKey(stringValue: "0", intValue: 0),
GenericCodingKey(stringValue: "firstName", intValue: nil)],
debugDescription: "Description for debugging purposes", underlyingError:
nil))`
### After
`DecodingError.valueNotFound: Expected value of type String but found
null instead. Path: [0].firstName. Debug description: Description for
debugging purposes`
## `test_decodingError_keyNotFound_nonNilUnderlyingError`
### Before
`keyNotFound(GenericCodingKey(stringValue: "name", intValue: nil),
Swift.DecodingError.Context(codingPath: [GenericCodingKey(stringValue:
"0", intValue: 0), GenericCodingKey(stringValue: "address", intValue:
nil), GenericCodingKey(stringValue: "city", intValue: nil)],
debugDescription: "Just some info to help you out", underlyingError:
Optional(main.GenericError(name: "hey, who turned out the lights?"))))`
### After
`DecodingError.keyNotFound: Key \'name\' not found in keyed decoding
container. Path: [0].address.city. Debug description: Just some info to
help you out. Underlying error: GenericError(name: "hey, who turned out
the lights?")`
## `test_decodingError_typeMismatch_nilUnderlyingError`
### Before
`typeMismatch(Swift.String, Swift.DecodingError.Context(codingPath:
[GenericCodingKey(stringValue: "0", intValue: 0),
GenericCodingKey(stringValue: "address", intValue: nil),
GenericCodingKey(stringValue: "city", intValue: nil),
GenericCodingKey(stringValue: "birds", intValue: nil),
GenericCodingKey(stringValue: "1", intValue: 1),
GenericCodingKey(stringValue: "name", intValue: nil)], debugDescription:
"This is where the debug description goes", underlyingError: nil))`
### After
`DecodingError.typeMismatch: expected value of type String. Path:
[0].address.city.birds[1].name. Debug description: This is where the
debug description goes`
## `test_decodingError_dataCorrupted_nonEmptyCodingPath`
### Before
`dataCorrupted(Swift.DecodingError.Context(codingPath:
[GenericCodingKey(stringValue: "first", intValue: nil),
GenericCodingKey(stringValue: "second", intValue: nil),
GenericCodingKey(stringValue: "2", intValue: 2)], debugDescription:
"There was apparently some data corruption!", underlyingError:
Optional(main.GenericError(name: "This data corruption is getting out of
hand"))))`
### After
`DecodingError.dataCorrupted: Data was corrupted. Path: first.second[2].
Debug description: There was apparently some data corruption!.
Underlying error: GenericError(name: "This data corruption is getting
out of hand")`
## `test_decodingError_valueNotFound_nonNilUnderlyingError`
### Before
`valueNotFound(Swift.Int, Swift.DecodingError.Context(codingPath:
[GenericCodingKey(stringValue: "0", intValue: 0),
GenericCodingKey(stringValue: "population", intValue: nil)],
debugDescription: "Here is the debug description for value-not-found",
underlyingError: Optional(main.GenericError(name: "these aren\\\'t the
droids you\\\'re looking for"))))`
### After
`DecodingError.valueNotFound: Expected value of type Int but found null
instead. Path: [0].population. Debug description: Here is the debug
description for value-not-found. Underlying error: GenericError(name:
"these aren\\\'t the droids you\\\'re looking for")`
##
`test_encodingError_invalidValue_emptyCodingPath_nonNilUnderlyingError`
### Before
`invalidValue(345, Swift.EncodingError.Context(codingPath: [],
debugDescription: "You cannot do that!", underlyingError:
Optional(main.GenericError(name: "You really cannot do that"))))`
### After
`EncodingError.invalidValue: 345 (Int). Debug description: You cannot do
that!. Underlying error: GenericError(name: "You really cannot do
that")`
## `test_decodingError_typeMismatch_nonNilUnderlyingError`
### Before
`typeMismatch(Swift.String, Swift.DecodingError.Context(codingPath:
[GenericCodingKey(stringValue: "0", intValue: 0),
GenericCodingKey(stringValue: "address", intValue: nil),
GenericCodingKey(stringValue: "1", intValue: 1),
GenericCodingKey(stringValue: "street", intValue: nil)],
debugDescription: "Some debug description", underlyingError:
Optional(main.GenericError(name: "some generic error goes here"))))`
### After
`DecodingError.typeMismatch: expected value of type String. Path:
[0].address[1].street. Debug description: Some debug description.
Underlying error: GenericError(name: "some generic error goes here")`
## `test_encodingError_invalidValue_emptyCodingPath_nilUnderlyingError`
### Before
`invalidValue(123, Swift.EncodingError.Context(codingPath: [],
debugDescription: "You cannot do that!", underlyingError: nil))`
### After
`EncodingError.invalidValue: 123 (Int). Debug description: You cannot do
that!`
## `test_decodingError_keyNotFound_nilUnderlyingError`
### Before
`keyNotFound(GenericCodingKey(stringValue: "name", intValue: nil),
Swift.DecodingError.Context(codingPath: [GenericCodingKey(stringValue:
"0", intValue: 0), GenericCodingKey(stringValue: "address", intValue:
nil), GenericCodingKey(stringValue: "city", intValue: nil)],
debugDescription: "How would you describe your relationship with your
debugger?", underlyingError: nil))`
### After
`DecodingError.keyNotFound: Key \'name\' not found in keyed decoding
container. Path: [0]address.city. Debug description: How would you
describe your relationship with your debugger?`
## `test_decodingError_dataCorrupted_emptyCodingPath`
### Before
`dataCorrupted(Swift.DecodingError.Context(codingPath: [],
debugDescription: "The given data was not valid JSON", underlyingError:
Optional(main.GenericError(name: "just some data corruption"))))`
### After
`DecodingError.dataCorrupted: Data was corrupted. Debug description: The
given data was not valid JSON. Underlying error: GenericError(name:
"just some data corruption")`
##
`test_encodingError_invalidValue_nonEmptyCodingPath_nonNilUnderlyingError`
### Before
`invalidValue(456, Swift.EncodingError.Context(codingPath:
[GenericCodingKey(stringValue: "first", intValue: nil),
GenericCodingKey(stringValue: "second", intValue: nil),
GenericCodingKey(stringValue: "2", intValue: 2)], debugDescription: "You
cannot do that!", underlyingError: Optional(main.GenericError(name: "You
really cannot do that"))))`
### After
`EncodingError.invalidValue: 456 (Int). Path: first.second[2]. Debug
description: You cannot do that!. Underlying error: GenericError(name:
"You really cannot do that")`
Inspired by #84826, I've dusted off and completely reworked a native
implementation of integer-to-string conversion.
Besides existing tests in this repository, the core of the
implementation has been comprehensively tested in a separate package for
all bases between 2–36 to demonstrate identical output for all 8-bit and
16-bit values, and for randomly generated 32-bit, 64-bit, and 128-bit
values.
Resolves#51902.
<!--
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!
-->
Optimize (the very inefficient) RawRepresentable comparison function call to a simple compare of enum tags.
For example,
```
enum E: String {
case a, b, c
}
```
is compared by getting the raw values of both operands and doing a string compare.
This peephole optimizations replaces the call to such a comparison function with a direct compare of the enum tags, which boils down to a single integer comparison instruction.
rdar://151788987
The new generalization sometimes causes a runtime hang that I’m still analyzing. The original declaration should be considered more specific for preexisting use cases, eliminating the source compatibility issue.
`func type(of:)` is wholly magical, but it does have a signature in the stdlib (mostly for documentation purposes), and it currently requires its input to be copyable and escapable.
`type(of:)` is actually usable on all entities, so it seems desirable to update its signature to reflect this.
Additionally, this seems like a good time to mark its exported symbol obsolete. I don’t expect anyone would ever link to it (unless there is/was a bug), so in theory we could also silently remove it — but explicitly marking it as legacy ABI seems the least risky option.
We cannot currently express its proper lifetime semantics: its result’s lifetime should depend on the intersection of the lifetime of the left argument and the lifetime of the result of the right argument.
`@lifetime(optional, defaultValue.result)` is what we want, but the `.result` part is not currently expressible. (Tying the dependency on the closure argument itself may be a viable option, but we aren’t confident enough to ship it like that yet.)
Introduce a marker protocol SendableMetatype that is used to indicate
when the metatype of a type will conform to Sendable. Specifically,
`T: SendableMetatype` implies `T.Type: Sendable`. When strict
metatype sendability is enabled, metatypes are only sendable when `T:
SendableMetatype`.
All nominal types implicitly conform to `SendableMetatype`, as do the
various builtin types, function types, etc. The `Sendable` marker
protocol now inherits from `SendableMetatype`, so that `T: Sendable`
implies `T.Type: Sendable`.
Thank you Slava for the excellent idea!
This PR adds basic support for storing lifetime dependence information,
transform Span return types, and generate lifetime annotations.
rdar://139074571