[swift-evolution] Possible issue with SE-0166 Swift Archival & Serialization implementation

Gwendal Roué gwendal.roue at gmail.com
Thu Jun 8 10:27:04 CDT 2017

> Le 8 juin 2017 à 16:51, James Froggatt via swift-evolution <swift-evolution at swift.org> a écrit :
> I've just been trying out the new Coding protocol, and was rather surprised when trying to implement the `encode(to encoder: Encoder)` method.
> The Swift evolution proposal provides the following example code:
>    public func encode(to encoder: Encoder) throws {
>        // Generic keyed encoder gives type-safe key access: cannot encode with keys of the wrong type.
>        let container = encoder.container(keyedBy: CodingKeys.self)
>        // The encoder is generic on the key -- free key autocompletion here.
>        try container.encode(latitude, forKey: .latitude)
>        try container.encode(longitude, forKey: .longitude)
>    }
> Here, container is stored as a `let` value, and uses reference semantics, while the proposal also clearly lists these `encode` methods as mutating. With the current implementation of the proposal, the container must be stored as a `var`, which leads to code like the following:
>    var container = encoder.singleValueContainer()
>    try container.encode(data)

Yes, practically speaking and with latest Swift 4, the container needs to be declared as `var`.

I admit it's weird, and feels unnatural:

   public func encode(to encoder: Encoder) throws {
       // A mutated value that nobody consumes: so weird.
       var container = encoder.container(keyedBy: CodingKeys.self)
       try container.encode(latitude, forKey: .latitude)
       try container.encode(longitude, forKey: .longitude)

> This clearly wont work as expected if the container were to have value semantics, and writing code like this feels plain wrong. Is SE-0166 really intended to work with referrence-type encoders only?

Actually, it can work with encoder/containers that have value semantics, and forward the mutations somewhere else (for example to a closure which fills a mutating container).

But this is again bizarre, and contrieved: https://github.com/groue/GRDB.swift/blob/15bfe5f6cf76070cfb17216223bdebc6b158d654/GRDB/Record/Persistable%2BEncodable.swift

You make me think that those structs should swiftly be refactored into reference types.


More information about the swift-evolution mailing list