<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="">I’ve been working on implementing <a href="https://github.com/apple/swift-evolution/blob/master/proposals/0111-remove-arg-label-type-significance.md" class="">SE-0111: Remove type system significance of function argument labels</a>. Actually implementing this feature completely requires major surgery to the type system, ASTs, and so on. <a href="https://github.com/apple/swift/commit/847b78245a473cc7160e45289311c85b6d6365b5" class="">While</a> <a href="https://github.com/apple/swift/commit/604adff1bdb9c6f515accd284156af4fe8153cde" class="">I</a> <a href="https://github.com/apple/swift/commit/5cce5c4d1d6121cc812d63f74441a612c33f5226" class="">am</a> <a href="https://github.com/apple/swift/commit/b40c89d4c6777bb69c3f7efe0e8ab8748c476994" class="">making</a> <a href="https://github.com/apple/swift/commit/e4d8f486a81021a2f66d8796dd3acaff3e02e4db" class="">progress</a> on this feature, it’s become clear that I cannot finish this in the Swift 3 time frame.</div><div class=""><br class=""></div><div class="">On the other hand, this is a source-breaking change that we’ve accepted for Swift 3, and it’s one that is hard to implement for Swift 4 in a way that also allows us to implement the Swift 3 model in the same compiler. Rock, meet hard place.</div><div class=""><br class=""></div><div class="">So, I’m going to try a new implementation strategy, which (I think) will allow us to get the behavior of SE-0111 but without refactoring the whole world. Essentially, we need the argument labels to persist in the type system when we’re performing a call to a function. In all other cases, the argument labels should be stripped from the type. Note that we can determine *syntactically* whether a particular declaration reference is a direct callee, which means we can indicate when a particular reference should have argument labels (for call matching) or nor (for unapplied references to a function). For example, given:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>func f(a: Int, b: Int) -> Int { … }</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let f1 = f(a: 1, b: 1) // treat ‘f’ as having type (a: Int, b: Int) -> Int, because we need argument labels for type checking</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let f2 = f // treat “f’ as having type (Int, Int) -> Int, because argument labels aren’t part of the type of ‘f’ (conceptually)</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let f3 = f(a:b:)(1, 2) // treat ‘f’ as having type (Int, Int) -> Int, because references that include the argument labels don’t need further matching of the argument labels</div><div class=""><br class=""></div><div class="">References to instances methods on a metatype are a bit more interesting, because of the curried ’Self’, but can still be handled syntactically:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>struct X {</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span> func g(a: Int, b: Int) -> Int { … }</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let x = X()</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let g1 = X.g // treat “X.g” as having type (X) -> (Int, Int) -> Int, because argument labels aren’t part of the type of ‘g’ (conceptually)</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let g2 = X.g(x) // treat “X.g” as having type (X) -> (Int, Int) -> Int, because argument labels aren’t part of the type of ‘g’ (conceptually)</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let g3 = X.g(x)(a: 1, b: 2) // treat “X.g” has having type (X) -> (a: Int, b: Int) -> Int, because the argument labels are needed to match up the arguments at the call site</div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let g3 = X.g(a:b:)(x)(1, 2) // treat “X.g” has having type (X) -> (Int, Int) -> Int, because references that include the argument labels don’t need further matching of those argument labels</div></div><div class=""><br class=""></div><div class="">We can deal with this by, basically, computing the number of direct applications to a given declaration and recording that in the AST. Then we use that information when forming a reference to the given function declaration.</div><div class=""><br class=""></div><div class="">Along with this, we eliminate the ability to write a function type with argument labels in the type system, so we get the “var f: (_ a: Int, _ b: Int) -> Int” syntactic change as well.</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>