> On Mar 16, 2017, at 10:21 AM, Itai Ferber <[email protected]> wrote:
> 
> On 15 Mar 2017, at 19:12, Joe Groff wrote:
> 
> 
> On Mar 15, 2017, at 6:46 PM, Itai Ferber <[email protected]> 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).

AnyCollection doesn't have any special compiler magic. AnyHashable's only magic 
is that it has implicit conversions, but that would become normal behavior once 
it can be replaced by a plain Hashable existential type.

-Joe
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to