<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body 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=""> typealias Index = Int</font></div></div><div class=""><div class=""><font face="Menlo" class=""> </font></div></div><div class=""><div class=""><font face="Menlo" class=""> var startIndex: Int {</font></div></div><div class=""><div class=""><font face="Menlo" class=""> return 0</font></div></div><div class=""><div class=""><font face="Menlo" class=""> }</font></div></div><div class=""><div class=""><font face="Menlo" class=""><br class=""></font></div></div><div class=""><div class=""><font face="Menlo" class=""> var endIndex: Int {</font></div></div><div class=""><div class=""><font face="Menlo" class=""> return 1</font></div></div><div class=""><div class=""><font face="Menlo" class=""> }</font></div></div><div class=""><div class=""><font face="Menlo" class=""><br class=""></font></div></div><div class=""><div class=""><font face="Menlo" class=""> subscript(index: Int) -> String {</font></div></div><div class=""><div class=""><font face="Menlo" class=""> return ""</font></div></div><div class=""><div class=""><font face="Menlo" class=""> }</font></div></div><div class=""><div class=""><font face="Menlo" class=""><br class=""></font></div></div><div class=""><div class=""><font face="Menlo" class=""> func index(after i: Int) -> Int {</font></div></div><div class=""><div class=""><font face="Menlo" class=""> return 1</font></div></div><div class=""><div class=""><font face="Menlo" class=""> }</font></div></div><div class=""><div class=""><font face="Menlo" class=""><br class=""></font></div></div><div class=""><div class=""><font face="Menlo" class=""> func index(before i: Int) -> Int {</font></div></div><div class=""><div class=""><font face="Menlo" class=""> return 0</font></div></div><div class=""><div class=""><font face="Menlo" class=""> }</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=""> associatedtype Indices : _RandomAccessIndexable, BidirectionalCollection</font></div></div><div class=""><div class=""><font face="Menlo" class=""> = DefaultRandomAccessIndices<Self></font></div></div><div class=""><font face="Menlo" class=""> 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<Self> {</font></div></div><div class=""><div class=""><font face="Menlo" class=""> public var indices: DefaultRandomAccessIndices<Self> { }</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, </font></div></div><div class=""><div class=""><font face="Menlo" class=""> Index.Stride == IndexDistance,</font></div></div><div class=""><div class=""><font face="Menlo" class=""> Indices == CountableRange<Index> {</font></div></div><div class=""><div class=""><font face="Menlo" class=""><br class=""></font></div></div><div class=""><div class=""><font face="Menlo" class=""> public var indices: CountableRange<Index> {</font></div></div><div class=""><div class=""><font face="Menlo" class=""> return startIndex..<endIndex</font></div></div><div class=""><div class=""><font face="Menlo" class=""> }</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<ReferenceCollection> and CountableRange<Int> 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 class=""><br class=""></div><div class="">For reference, Swift 3.0.1 picked DefaultRandomAccessIndices<ReferenceCollection>, current Swift master picks CountableRange<Int>, 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></body></html>