- Proposal: SE-0396
- Author: Nate Cook
- Review Manager: Tony Allevato
- Status: Implemented (Swift 5.9)
- Implementation: apple/swift#64899
- Review: (pitch) (review) (acceptance)
Extend Never
so that it conforms to the Encodable
and Decodable
protocols, together known as Codable
.
Swift can synthesize Codable
conformance for any type that has Codable
members. Generic types often participate in this synthesized conformance by constraining their generic parameters, like this Either
type:
enum Either<A, B> {
case left(A)
case right(B)
}
extension Either: Codable where A: Codable, B: Codable {}
In this way, Either
instances where both generic parameters are Codable
are Codable
themselves, such as an Either<Int, Double>
. However, since Never
isn't Codable
, using Never
as one of the parameters blocks the conditional conformance, even though it would be perfectly fine to encode or decode a type like Either<Int, Never>
.
The standard library should add Encodable
and Decodable
conformance to the Never
type.
The Encodable
conformance is simple — since it's impossible to have a Never
instance, the encode(to:)
method can simply be empty.
The Decodable
protocol requires the init(from:)
initializer, which clearly can't create a Never
instance. Because trying to decode invalid input isn't a programmer error, a fatal error would be inappropriate. Instead, the implementation throws a DecodingError.typeMismatch
error if decoding is attempted.
If existing code already declares Codable
conformance, that code will begin to emit a warning: e.g. Conformance of 'Never' to protocol 'Encodable' was already stated in the type's module 'Swift'
.
The new conformance shouldn't differ from existing conformances, since it isn't possible to construct an instance of Never
.
The proposed change is additive and does not change any existing ABI.
The new conformance will have availability annotations.
None.
A previous iteration of this proposal used DecodingError.dataCorrupted
as the error thrown from the Decodable
initializer. Since that error is typically used for syntactical errors, such as malformed JSON, the typeMismatch
error is now used instead. A custom error type could be created for this purpose, but as typeMismatch
already exists as documented API, and provides the necessary information for a developer to understand the error, its use is appropriate here.