<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">&lt;<a href="mailto:dabrahams@apple.com" target="_blank">dabrahams@apple.com</a>&gt;</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 &lt;austinzheng-AT-gmail.com&gt; wrote:<br>
<br>
&gt; We might be talking past each other. I think Matthew is talking about using<br>
&gt; an existential outside the context of generic functions. For example,<br>
&gt; something like this should be trap-proof (as long as &#39;x&#39; is immutable,<br>
&gt; 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&#39;m using gmail in the browser. I&#39;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>
&gt; func copySequenceIntoArray(x: Any&lt;Sequence where .Iterator.Element == Int&gt;) -&gt; [Int] {<br>
&gt;       var buffer : [Int] = []<br>
&gt;         // Stupid implementation to make a point<br>
&gt;       var iterator : x.Iterator = x.makeIterator()<br>
&gt;       while true {<br>
&gt;               let nextItem : Int? = iterator.next()<br>
&gt;               if let nextItem = nextItem {<br>
&gt;                       buffer.append(nextItem)<br>
&gt;               } else {<br>
&gt;                       return buffer<br>
&gt;               }<br>
&gt;       }<br>
&gt; }<br>
<br>
</span>Presumably this would “work” as well?<br>
<br>
  typealias IntSequence = Any&lt;Sequence where .Iterator.Element == Int&gt;<br>
  func f(x: IntSequence, y: IntSequence) {<br>
    var i = x.makeIterator()<br>
    i = y.makeIterator()     // &lt;== NO TRAP HERE, EVER.<br>
<span class="">  }<br></span></blockquote><div><br></div><div>This presumably wouldn&#39;t compile. The sort-of-dependent-type &quot;x.Iterator&quot; (return value of x.makeIterator(); inferred as type of &#39;i&#39;), and &quot;y.Iterator&quot; (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>
&gt; Even this would never trap as well:<br>
&gt;<br>
&gt; func copySequenceIntoArray&lt;T&gt;(x: Any&lt;Sequence where .Iterator.Element == T&gt;) -&gt; [T] {<br>
&gt;       var buffer : [T] = []<br>
&gt;       for item in x {<br>
&gt;               buffer.append(item)<br>
&gt;       }<br>
&gt;       return buffer<br>
&gt; }<br>
<br>
</span>Sure, this one is simple because the associated type is never even<br>
exposed.<br>
<span class=""><br>
&gt; Where we run into difficulty is something like this (forgive my abuse<br>
&gt; of the collections API; I don&#39;t remember all the new indexing APIs off<br>
&gt; the top of my head):<br>
&gt;<br>
&gt; func doSomething&lt;T : Collection where T.Element == Int&gt;(x: T, y: T) {<br>
&gt;       // Get indexes out of x and use them to index into y<br>
&gt;       var idx = x.startIndex<br>
&gt;       while (idx != x.endIndex || idx != y.endIndex) {<br>
&gt;               print(x[idx])<br>
&gt;               print(y[idx])<br>
&gt;               idx = x.nextIndex(idx)<br>
&gt;       }<br>
&gt; }<br>
&gt; let someSeq : Any&lt;Collection where .Element == Int&gt; = // ...<br>
&gt; let anotherSeq : Any&lt;Collection where .Element == Int&gt; = // ...<br>
&gt; // Trouble!<br>
&gt; // someSeq and anotherSeq are the same existential type<br>
&gt; // But the concrete index types within each of the existential variables may be different<br>
&gt; doSomething(someSeq, anotherSeq)<br>
&gt;<br>
&gt; may be different<br>
&gt; doSomething(someSeq, anotherSeq)<br>
&gt;<br>
&gt; It&#39;s this situation (using an existential type to fulfill a generic<br>
&gt; type parameter constrained to the same requirements that comprise that<br>
&gt; existential) that requires either of the two options that Dave<br>
&gt; presented, due to our lack of compile-time type information about the<br>
&gt; fulfilling type&#39;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&#39;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_&lt;C: Collection&gt;(c: C, i: C.Index) -&gt; C.Collection.Element {<br>
    return c[i]<br>
  }<br>
<br>
  typealias IntCollection = Any&lt;Collection where Element == Int&gt;<br>
  let c1: IntCollection = ...<br>
  let c2: IntCollection = c1[3..&lt;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>