> On Jun 8, 2016, at 3:18 PM, Dave Abrahams via swift-evolution 
> <[email protected]> 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)


Russ


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

Reply via email to