<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=""><b class="">Introduction<br class=""></b><br class="">This proposal suggests moving the existing @noescape and @autoclosure attributes from being declaration attributes on a parameter to being type attributes. &nbsp;This&nbsp;improves consistency and reduces redundancy within the language, e.g. aligning with the previous Swift 3 decision to move “inout”, and making declaration and type syntax more consistent.&nbsp;<br class=""><br class="">Swift-evolution thread: &lt;you are here&gt;<br class=""><br class=""><b class="">Motivation<br class=""></b><br class="">Chris Eidhof noticed an emergent result of removing our currying syntax: it broke some useful code using @noescape, because we only allowed it on parameter declarations, not on general things-of-function-type. &nbsp;This meant that manually curried code like this:<br class=""><br class="">func curriedFlatMap&lt;A, B&gt;(x: [A]) -&gt; (@noescape A -&gt; [B]) -&gt; [B] {<br class="">&nbsp;&nbsp;&nbsp;return { f in<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x.flatMap(f)<br class="">&nbsp;&nbsp;&nbsp;}<br class="">}<br class=""><br class="">Was rejected. &nbsp;Fixing this was straight-forward (<a href="https://github.com/apple/swift/commit/c3c6beac72bc0368030f06d52c46b6444fc48dbd" class="">https://github.com/apple/swift/commit/c3c6beac72bc0368030f06d52c46b6444fc48dbd</a>), but required @noescape being allowed on arbitrary function types. &nbsp;Now that we have that, these two declarations are equivalent:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>func f(@noescape fn : () -&gt; ()) {} &nbsp;// declaration attribute<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>func f(fn : @noescape () -&gt; ()) {} &nbsp;// type attribute.<br class=""><br class="">Further evaluation of the situation found that @autoclosure (while less pressing) has the exact same problem. &nbsp;That said, it is currently in a worse place than @noescape because you cannot actually spell the type of a function that involves it. &nbsp; Consider an autoclosure-taking function like this:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>func f2(@autoclosure a : () -&gt; ()) {}<br class=""><br class="">You can use it as you’d expect, e.g.:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>f2(print("hello”))<br class=""><br class="">Of course, f2 is a first class value, so you can assign it:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let x = f2<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>x(print("hello"))<br class=""><br class="">This works, because x has type "(@autoclosure () -&gt; ()) -&gt; ()”. &nbsp;You can see this if you force a type error:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let y : Int = x // error: cannot convert value of type '(@autoclosure () -&gt; ()) -&gt; ()' to specified type 'Int'<br class=""><br class="">However, you can’t write this out explicitly:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let x2 : (@autoclosure () -&gt; ()) -&gt; () = f2<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>// error: attribute can only be applied to declarations, not types<br class=""><br class="">This is unfortunate because it is an arbitrary inconsistency in the language, and seems silly that you can use type inference but not manual specification for the declaration of x2.<br class=""><br class=""><b class="">Proposed solution<br class=""></b><br class="">The solution solution is straight-forward: disallow @noescape and @autoclosure on declarations, and instead require them on the types. &nbsp;This means that only the type-attribute syntax is supported:<div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>func f(fn : @noescape () -&gt; ()) {} &nbsp; &nbsp; &nbsp;// type attribute.<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>func f2(a : @autoclosure () -&gt; ()) {} &nbsp;// type attribute.</div><div class=""><br class="">This aligns with the syntax used for types, since the type of “f” is “(_:&nbsp;@noescape () -&gt; ()) -&gt; ()”, and the type of “f2” is “(_ : @autoclosure () -&gt; ()) -&gt; ()”. &nbsp;This fixes the problem with x2, and eliminates the redundancy between the @noescape forms.</div><div class=""><br class=""><b class="">Impact on existing code<br class=""></b><br class="">This breaks existing code that uses these in the old position, so it would be great to roll this out with the other disruptive changes happening in Swift 3. &nbsp;The Swift 3 migrator should move these over, and has the information it needs to do a perfect migration in this case.</div><div class=""><br class=""></div><div class="">For the compiler behavior, given that Swift 2.2 code will be source incompatible with Swift 3 code in general, it seems best to make these a hard error in the final Swift 3 release. &nbsp;It would make sense to have a deprecation warning period for <a href="http://swift.org" class="">swift.org</a> projects like corelibs and swiftpm, and other open source users tracking the public releases though.</div><div class=""><div class=""><br class=""></div><div class="">-Chris</div><div class=""><div class=""><br class=""></div><div class=""><br class=""></div></div></div></body></html>