<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div>Voting for 1. &nbsp;This is an ambiguity in stdlib through and through IMO.<br><br>~Robert Widmann</div><div><br>2016/11/07 22:07、Mark Lacey via swift-dev &lt;<a href="mailto:swift-dev@swift.org">swift-dev@swift.org</a>&gt; のメッセージ:<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html charset=utf-8"><br class=""><div><blockquote type="cite" class=""><div class="">On Nov 7, 2016, at 6:16 PM, Douglas Gregor via swift-dev &lt;<a href="mailto:swift-dev@swift.org" class="">swift-dev@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Hi all,<div class=""><br class=""></div><div class="">While working on the type checker, I came across an interesting case for associated type inference with the ‘Indices’ type of RandomAccessCollection. At issue is a simple model of RandomAccessCollection where the Index type is Int:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><font face="Menlo" class="">class ReferenceCollection : RandomAccessCollection {</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; typealias Index = Int</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp;&nbsp;</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; var startIndex: Int {</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp; return 0</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; }</font></div></div><div class=""><div class=""><font face="Menlo" class=""><br class=""></font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; var endIndex: Int {</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp; return 1</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; }</font></div></div><div class=""><div class=""><font face="Menlo" class=""><br class=""></font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; subscript(index: Int) -&gt; String {</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp; return ""</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; }</font></div></div><div class=""><div class=""><font face="Menlo" class=""><br class=""></font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; func index(after i: Int) -&gt; Int {</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp; return 1</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; }</font></div></div><div class=""><div class=""><font face="Menlo" class=""><br class=""></font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; func index(before i: Int) -&gt; Int {</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp; return 0</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; }</font></div></div><div class=""><div class=""><font face="Menlo" class="">}</font></div></div></blockquote><div class=""><br class=""></div><div class="">What’s the inferred associated Indices? The RandomAccessIterator protocol has a default:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Menlo" class="">protocol RandomAccessCollection {</font></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp; associatedtype Indices : _RandomAccessIndexable, BidirectionalCollection</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; = DefaultRandomAccessIndices&lt;Self&gt;</font></div></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; var indices: Indices { get }</font></div><div class=""><font face="Menlo" class="">}</font></div></blockquote><div class=""><br class=""></div><div class="">which will kick in if nothing else can be inferred. There is also an implementation for this defaulted case in a protocol extension from which we can infer Indices:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><font face="Menlo" class="">extension RandomAccessCollection where Indices == DefaultRandomAccessIndices&lt;Self&gt; {</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp;public var indices: DefaultRandomAccessIndices&lt;Self&gt; { }</font></div></div><div class=""><div class=""><font face="Menlo" class="">}</font></div></div></blockquote><div class=""><br class=""></div><div class="">Those line up, which is easy, but there is *another* protocol extension of RandomAccessIterator from which we can infer Indices:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class=""><font face="Menlo" class="">extension RandomAccessCollection</font></div></div><div class=""><div class=""><font face="Menlo" class="">where Index : Strideable,&nbsp;</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; Index.Stride == IndexDistance,</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; Indices == CountableRange&lt;Index&gt; {</font></div></div><div class=""><div class=""><font face="Menlo" class=""><br class=""></font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; public var indices: CountableRange&lt;Index&gt; {</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; &nbsp; return startIndex..&lt;endIndex</font></div></div><div class=""><div class=""><font face="Menlo" class="">&nbsp; }</font></div></div><div class=""><div class=""><font face="Menlo" class="">}</font></div></div></blockquote><div class=""><br class=""></div><div class="">Note that both DefaultRandomAccessIndices&lt;ReferenceCollection&gt; and CountableRange&lt;Int&gt; would be valid inferences for Indices. We have three options:</div><div class=""><br class=""></div><div class="">1) Consider type inference to be ambiguous, because there is no natural ordering between the two protocol extensions (they have incompatible same-type constraints on the associated type Indices).</div><div class="">2) Consider the first protocol extension to “win” because… we prefer the extension which corresponds to the associated type default (?). This would be consistent with a world where we don’t have associated type inference at all. (It also matches Swift 3.0.1’s behavior).</div><div class="">3) Consider the second protocol extension to “win” because…the other protocol extension corresponds to the associated type default, and could therefore be considered to be a lowest-common-denominator implementation only there to provide the most basic defaults.</div></div></div></blockquote><div><br class=""></div>I can see the appeal of option 3, but IMO anything other than option 1 seems pretty brittle. Presumably with that option, and with the class providing a typealias for Indices, you would no longer have an ambiguity and the code would compile, correct?</div><div><br class=""></div><div>Mark</div><div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class="">For reference, Swift 3.0.1 picked DefaultRandomAccessIndices&lt;ReferenceCollection&gt;, current Swift master picks CountableRange&lt;Int&gt;, and my work-in-progress to improve the type checker calls it ambiguous, hence the question :)</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>- Doug</div><div class=""><br class=""></div></div>_______________________________________________<br class="">swift-dev mailing list<br class=""><a href="mailto:swift-dev@swift.org" class="">swift-dev@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-dev">https://lists.swift.org/mailman/listinfo/swift-dev</a><br class=""></div></blockquote></div><br class=""></div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-dev mailing list</span><br><span><a href="mailto:swift-dev@swift.org">swift-dev@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-dev">https://lists.swift.org/mailman/listinfo/swift-dev</a></span><br></div></blockquote></body></html>