<div dir="ltr">(inline)<br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Jun 8, 2016 at 3:18 PM, Dave Abrahams <span dir="ltr"><<a href="mailto:dabrahams@apple.com" target="_blank">dabrahams@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=""><br>
on Wed Jun 08 2016, Austin Zheng <austinzheng-AT-gmail.com> wrote:<br>
<br>
> We might be talking past each other. I think Matthew is talking about using<br>
> an existential outside the context of generic functions. For example,<br>
> something like this should be trap-proof (as long as 'x' is immutable,<br>
> which it is in this example):<br>
<br>
</span>[Ugh, Austin, your mail program is stripping the tabs out of the<br>
plaintext part so the indendation is lost. Grabbing from browser...]<br></blockquote><div><br></div><div>Sorry! I'm using gmail in the browser. I'll stay away from tabs...</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<span class=""><br>
> func copySequenceIntoArray(x: Any<Sequence where .Iterator.Element == Int>) -> [Int] {<br>
> var buffer : [Int] = []<br>
> // Stupid implementation to make a point<br>
> var iterator : x.Iterator = x.makeIterator()<br>
> while true {<br>
> let nextItem : Int? = iterator.next()<br>
> if let nextItem = nextItem {<br>
> buffer.append(nextItem)<br>
> } else {<br>
> return buffer<br>
> }<br>
> }<br>
> }<br>
<br>
</span>Presumably this would “work” as well?<br>
<br>
typealias IntSequence = Any<Sequence where .Iterator.Element == Int><br>
func f(x: IntSequence, y: IntSequence) {<br>
var i = x.makeIterator()<br>
i = y.makeIterator() // <== NO TRAP HERE, EVER.<br>
<span class=""> }<br></span></blockquote><div><br></div><div>This presumably wouldn't compile. The sort-of-dependent-type "x.Iterator" (return value of x.makeIterator(); inferred as type of 'i'), and "y.Iterator" (return type of y.makeIterator()) would not be considered equivalent.</div><div><br></div><div>(As Doug mentioned in a recent email, it would only be feasible to expose such types on immutable values. The intention is not to allow the largely-meaningless code that follows:</div><div><br></div><div>func f(x: IntSequence, y: IntSequence) {</div><div> var z : IntSequence = x</div><div> var something : z.Iterator = x.makeIterator()</div><div> z = y</div><div> something = y.makeIterator()</div><div> // ...</div><div>}</div><div>)<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
<br>
> Even this would never trap as well:<br>
><br>
> func copySequenceIntoArray<T>(x: Any<Sequence where .Iterator.Element == T>) -> [T] {<br>
> var buffer : [T] = []<br>
> for item in x {<br>
> buffer.append(item)<br>
> }<br>
> return buffer<br>
> }<br>
<br>
</span>Sure, this one is simple because the associated type is never even<br>
exposed.<br>
<span class=""><br>
> Where we run into difficulty is something like this (forgive my abuse<br>
> of the collections API; I don't remember all the new indexing APIs off<br>
> the top of my head):<br>
><br>
> func doSomething<T : Collection where T.Element == Int>(x: T, y: T) {<br>
> // Get indexes out of x and use them to index into y<br>
> var idx = x.startIndex<br>
> while (idx != x.endIndex || idx != y.endIndex) {<br>
> print(x[idx])<br>
> print(y[idx])<br>
> idx = x.nextIndex(idx)<br>
> }<br>
> }<br>
> let someSeq : Any<Collection where .Element == Int> = // ...<br>
> let anotherSeq : Any<Collection where .Element == Int> = // ...<br>
> // Trouble!<br>
> // someSeq and anotherSeq are the same existential type<br>
> // But the concrete index types within each of the existential variables may be different<br>
> doSomething(someSeq, anotherSeq)<br>
><br>
> may be different<br>
> doSomething(someSeq, anotherSeq)<br>
><br>
> It's this situation (using an existential type to fulfill a generic<br>
> type parameter constrained to the same requirements that comprise that<br>
> existential) that requires either of the two options that Dave<br>
> presented, due to our lack of compile-time type information about the<br>
> fulfilling type's associated types.<br>
<br>
</span>Exactly. But much simpler cases will also either have to trap at<br>
runtime or be prohibited outright:<br></blockquote><div><br></div><div>Of course. I don't know what the right solution to this is yet.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
func subscript_<C: Collection>(c: C, i: C.Index) -> C.Collection.Element {<br>
return c[i]<br>
}<br>
<br>
typealias IntCollection = Any<Collection where Element == Int><br>
let c1: IntCollection = ...<br>
let c2: IntCollection = c1[3..<10]<br>
let c3: IntCollection = ...<br>
let c4: IntCollection = c1.reversed()<br>
<br>
// Note: the underlying index types are the same, and are supposed to<br>
// interoperate. What do you do (work/trap/nocompile)?<br>
_ = subscript_(c1, c2.startIndex)<br>
<br>
// The underlying index types happen to be the same, and are not<br>
// supposed to interoperate. What do you do (silently “work”/trap/nocompile)?<br>
_ = subscript_(c1, c3.startIndex)<br>
<br>
// The underlying index types are different. What do you do (trap/nocompile)?<br>
_ = subscript_(c1, c4.startIndex)<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
Dave<br>
</font></span></blockquote></div><br></div></div>