In trying out Swift 5.5's Codable synthesis for enums with associated values, I've hit a snag. When contained in a generic type, it isn't clear how to declare conformance. Consider the following:
struct Container<Element>: Codable {
let options: [Option]
}
extension Container {
enum Option: Codable {
case first (Element)
case second (Element)
}
}
This produces an error:
Type 'Container.Option' does not conform to protocol 'Encodable/Decodable'.
Hmm, well let's try extracting Codable conformance into its own extension:
extension Container: Codable where Element: Codable {}
extension Container.Option: Codable where Element: Codable {}
Now we get:
generic enum type 'Container.Option' is ambiguous without explicit generic parameters when matching value of type 'Container<Element>.Option'
Since I'm not trying to create a concrete type for Element, I'm not sure what generic parameters are needed in this case. I would assume this should work similar to Equatable conformance:
extension Container: Equatable where Element: Equatable {}
extension Container.Option: Equatable where Element: Equatable {}
This works as expected, so I don't understand what I'm missing with the Codable declaration. Is this intended behavior?
hisekaldma
(Jonathan Hise Kaldma)
2
I don't have Swift 5.5 handy, but it seems to me that this should work. If you change Container.Option to a struct, Codable synthesis works in 5.4 at least.
struct Container<Element> {
let options: [Option]
}
extension Container {
struct Option {
var first: Element
var second: Element
}
}
extension Container: Codable where Element: Codable {}
extension Container.Option: Codable where Element: Codable {}
Perhaps a workaround might be to move Option outside of Container and make it generic over Element? Like so:
struct Container<Element> {
let options: [Option<Element>]
}
enum Option<Element> {
case first (Element)
case second (Element)
}
extension Container: Codable where Element: Codable {}
extension Option: Codable where Element: Codable {}
Yes, this is reasonable workaround. What you lose with that approach is the 'namespace' isolation. I suppose I could live with it, but it seems like a hole that needs plugging. Appreciate the response!
1 Like
If it works for Equatable, it ought to work for Codable too. This is a beta specific issue, it does work as you'd expect on the main branch. I've filed [SR-14854] Codable synthesis for enums doesn't work with generics + type nesting · Issue #57201 · apple/swift · GitHub to track the fix being cherry-picked.
3 Likes