<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div>It makes sense, and worth the change, IMHO. <br><br>Pierre</div><div><br>Le 10 mars 2016 à 06:38, Chris Lattner via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> a écrit :<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html charset=utf-8"><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. This 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. <br class=""><br class="">Swift-evolution thread: <you are here><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. This meant that manually curried code like this:<br class=""><br class="">func curriedFlatMap<A, B>(x: [A]) -> (@noescape A -> [B]) -> [B] {<br class=""> return { f in<br class=""> x.flatMap(f)<br class=""> }<br class="">}<br class=""><br class="">Was rejected. 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. 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 : () -> ()) {} // declaration attribute<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>func f(fn : @noescape () -> ()) {} // type attribute.<br class=""><br class="">Further evaluation of the situation found that @autoclosure (while less pressing) has the exact same problem. That said, it is currently in a worse place than @noescape because you cannot actually spell the type of a function that involves it. 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 : () -> ()) {}<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 () -> ()) -> ()”. 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 () -> ()) -> ()' 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 () -> ()) -> () = 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. 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 () -> ()) {} // type attribute.<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>func f2(a : @autoclosure () -> ()) {} // type attribute.</div><div class=""><br class="">This aligns with the syntax used for types, since the type of “f” is “(_: @noescape () -> ()) -> ()”, and the type of “f2” is “(_ : @autoclosure () -> ()) -> ()”. 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. 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. 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></div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></body></html>