[swift-evolution] [Proposal] Foundation Swift Archival & Serialization

Itai Ferber iferber at apple.com
Thu Mar 16 12:21:32 CDT 2017

On 15 Mar 2017, at 19:12, Joe Groff wrote:

>> On Mar 15, 2017, at 6:46 PM, Itai Ferber <iferber at apple.com> wrote:
>> Thanks Joe, and thanks for passing this along!
>> To those who are curious, we use abstract base classes for a 
>> cascading list of reasons:
>> 	• We need to be able to represent keyed encoding and decoding 
>> containers as abstract types which are generic on a key type
>> 	• There are two ways to support abstraction in this way: protocol 
>> & type constraints, and generic types
>> 		• Since Swift protocols are not generic, we unfortunately cannot 
>> write protocol KeyedEncodingContainer<Key : CodingKey> { ... }, which 
>> is the "ideal" version of what we're trying to represent
>> 	• Let's try this with a protocol first (simplified here):
>> protocol Container {
>>     associatedtype Key : CodingKey
>> }
>> func container<Key : CodingKey, Cont : Container>(_ type: Key.Type) 
>> -> Cont where Cont.Key == Key {
>>     // return something
>> }
>> This looks promising so far — let's try to make it concrete:
>> struct ConcreteContainer<K : CodingKey> : Container {
>>     typealias Key = K
>> }
>> func container<Key : CodingKey, Cont : Container>(_ type: Key.Type) 
>> -> Cont where Cont.Key == Key {
>>     return ConcreteContainer<Key>() // error: Cannot convert return 
>> expression of type 'ConcreteContainer<Key>' to return type 'Cont'
>> }
>> Joe or anyone from the Swift team can describe this better, but this 
>> is my poor-man's explanation of why this happens. Swift's type 
>> constraints are "directional" in a sense. You can constrain a type 
>> going into a function, but not out of a function. There is no type I 
>> could return from inside of container() which would satisfy this 
>> constraint, because the constraint can only be satisfied by turning 
>> Cont into a concrete type from the outside.
>> Okay, well let's try this:
>> func container... {
>>     return ConcreteContainer<Key>() as! Cont
>> }
>> This compiles fine! Hmm, let's try to use it:
>> container(Int.self) // error: Generic parameter 'Cont' could not be 
>> inferred
>> The type constraint can only be fulfilled from the outside, not the 
>> inside. The function call itself has no context for the concrete type 
>> that this would return, so this is a no-go.
>> 	• If we can't do it with type constraints in this way, is it 
>> possible with generic types? Yep! Generic types satisfy this without 
>> a problem. However, since we don't have generic protocols, we have to 
>> use a generic abstract base class to represent the same concept — 
>> an abstract container generic on the type of key which dynamically 
>> dispatches to the "real" subclassed type
>> Hopes that gives some simplified insight into the nature of this 
>> decision.
> I see. Protocols with associated types serve the same purpose as 
> generic interfaces in other languages, but we don't have the 
> first-class support for protocol types with associated type 
> constraints (a value of type `Container where Key == K`). That's 
> something we'd like to eventually support. In other places in the 
> standard library, we wrtie the type-erased container by hand, which is 
> why we have `AnySequence`, `AnyCollection`, and `AnyHashable`. You 
> could probably do something similar here; that would be a bit awkward 
> for implementers, but might be easier to migrate forward to where we 
> eventually want to be with the language.
> -Joe
Yep, that’s a good way to describe it.
We could potentially do that as well, but adding another type like 
`AnyHashable` or `AnyCollection` felt like a much more sweeping change, 
considering that those require some special compiler magic themselves 
(and we’d like to do as little of that as we can).
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170316/cba64008/attachment.html>

More information about the swift-evolution mailing list