[swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

Russ Bishop xenadu at gmail.com
Thu Jun 9 01:52:53 CDT 2016

> On Jun 8, 2016, at 3:18 PM, Dave Abrahams via swift-evolution <swift-evolution at swift.org> wrote:
> Exactly.  But much simpler cases will also either have to trap at
> runtime or be prohibited outright:
>  func subscript_<C: Collection>(c: C, i: C.Index) -> C.Collection.Element {
>    return c[i]
>  }
>  typealias IntCollection = Any<Collection where Element == Int>
>  let c1: IntCollection = ...
>  let c2: IntCollection = c1[3..<10]
>  let c3: IntCollection = ...
>  let c4: IntCollection = c1.reversed()
>  // Note: the underlying index types are the same, and are supposed to
>  // interoperate.  What do you do (work/trap/nocompile)?
>  _ = subscript_(c1, c2.startIndex)
>  // The underlying index types happen to be the same, and are not
>  // supposed to interoperate.  What do you do (silently “work”/trap/nocompile)?
>  _ = subscript_(c1, c3.startIndex)
>  // The underlying index types are different.  What do you do (trap/nocompile)?
>  _ = subscript_(c1, c4.startIndex)
> -- 
> Dave

Is it sufficient to say that unconstrained associated types cannot satisfy generic constraints so subscript_ can’t be called with startIndex? 
Presumably if you said Any<Collection where Element == Int, Index == Int> you could then call subscript_.

Not being a compiler expert another thought occurs to me: Can the type of an existential/unconstrained associated type be an unique anonymous type in the local scope? In this case c1.startIndex is of type a’; it cannot be stored in a global, passed to another function, etc. It is only usable in the current scope for interacting with c1. c2.startIndex would be of type b’, etc. This is similar to how anonymous types work in C#. The issues with func<X>(a: X, b: X) could in theory be solved the same way: require opening the existential in the local scope and validating that the actual types are identical before you can call func. 

In that sense you could say the types are really:

let c1: a’<IntCollection>
let c2: b’<IntCollection>
let c3: c’<IntCollection>
let c4: d’<IntCollection>

// accepts responsibility for a and b being different concrete types at runtime
func doIt(a: IntCollection, b: IntCollection) { }

// caller must prove a & b are same concrete type
func makeIt<C: Collection>(a: C, b: C) { }

They are completely separate types until proven otherwise and you can’t go passing them around unless the callee accepts responsibility for the dynamism or you prove exactly which type you’re talking about.

(I freely admit this may be nonsensical or impossible to implement reasonably in the compiler)


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160608/93b8c2e9/attachment.html>

More information about the swift-evolution mailing list