SE-0295: Codable synthesis for enums with associated values

I know the review period is long over, but I’d like to raise an issue that I think hasn’t been mentioned in the review thread or the proposal (apologies if I missed it).

The proposal is intended for enums that have at least one payload case, but it would also apply to enums that have no associated values and are not RawRepresentable.

If accepted, this code, which is currently a compile error because the enum is not RawRepresentable, would become valid:

enum Color: Codable {
  case red
  case yellow
}

I think the proposal text should specifically mention this case. I also think it’s very desirable that a no-payload, non-RawRepresentable enum encode itself in the same way as if it had strings as raw values. That is, the enum above should have the same encoding format as this one:

enum Color2: String, Codable {
  case red
  case yellow
}

If the formats were not the same, many people would forget to make their enums string-backed and be surprised about the encoded data.

Following the existing encoding format for RawRepresentable enums would mean no-payload cases should be encoded as @brentdax suggested, i.e. not nested inside a keyed container. If this isn't possible because the Decoder API doesn't allow it or we decide on a different format, it's a significant drawback for the proposal in my opinion.

1 Like

More generally, I'm against the proposal as written. I recognize that there's no obvious format that will satisfy all requirements, but I do think missing code synthesis for enums with payload is a significant gap in the language that Swift should eventually have an answer for. I listed one example in the previous post where I think the synthesis rules listed in the proposal are not the right defaults. I also agree with most of the other suggested changes made by @brentdax and others.

I remember there was a similar discussion about the encoding format used for Range’s Codable conformance (unkeyed vs. keyed container). SE-0239 eventually settled on using an unkeyed container. @tkremenek’s acceptance post for SE-0239 may be relevant to this discussion (emphasis mine):

For Range types, the Core Team concluded from the review conversation that an unkeyed container representation seems like a reasonable default, but also recognized from the discussion on this thread that there are cases where a keyed representation is preferred. What this review thread further illustrated is the need to make Codable more flexible to provide the encoding customizations needed to service different tasks. There is no set of defaults for encoding that will satisfy every use-case. Some use-cases will prioritize serialization performance over human readability, and quite often the inverse. The Core Team would like to encourage the community to channel the energy that appeared in this thread to discussing general enhancements to Codeable to make it more flexible and amendable to serving more use-cases more easily, and @itaiferber has initiated a thread to do just that .

@drexin Thank you for work on this!

3 Likes

I posted a pitch that would more clearly tie tuple codability to enums-with-associated-types codability here: New {De,En}codingContainer types to support enums with associated types (and tuples) - #4 by rpsm (Sorry if this branches the discussion, I didn't realize that this was still in review).

Basically the idea is to reveal the full structure of tuples and enums to the coding infrastructure via two new container types. I feel that this is a more flexible approach and could resolve some of the disagreements about details of how associated values are encoded and decoded because it would allow us to specify the behavior on the coder, instead of defining it language-wide.