<div dir="ltr">I seem to have hit a possibly related @escaping issue...<div><br></div><div>The following code worked without issue under Swift 2.x and earlier variants of Swift 3 but after the @escaping change (fairly sure that is what is at fault) it no longer compiles.</div><div><br></div><div><div>protocol Foo {</div><div>    // Happy</div><div>    func visitValues&lt;T&gt;(visitors: [(key: String, body: (T) throws -&gt; Void)]) throws</div><div><br></div><div>    // Happy</div><div>    func visitValues&lt;T&gt;(throwOnWrongType: Bool, visitors: [(key: String, body: (T) throws -&gt; Void)]) throws</div><div>}</div><div><br></div><div>protocol FooBar { // IGNORE ME - NOT PART OF ORIGINAL CODE</div><div>    // Unhappy - this is appearntly expected given prior emails in this thread</div><div>    // @escaping may only be applied to parameters of function type</div><div>    func visitValues&lt;T&gt;(visitors: [(key: String, body: @escaping (T) throws -&gt; Void)]) throws</div><div><br></div><div>    // Unhappy - this is appearntly expected given prior emails in this thread</div><div>    // @escaping may only be applied to parameters of function type</div><div>    func visitValues&lt;T&gt;(throwOnWrongType: Bool, visitors: [(key: String, body: @escaping (T) throws -&gt; Void)]) throws</div><div>}</div><div><br></div><div>// Provide a default implementation for the simple visitor version</div><div>extension Foo {</div><div>    // Happy</div><div>    func visitValues&lt;T&gt;(visitors: [(String, body: (T) throws -&gt; Void)]) throws {</div><div>        try self.visitValues(throwOnWrongType: false, visitors: visitors)</div><div>    }</div><div>}</div><div><br></div><div>// Unhappy</div><div>// error: type &#39;RealFoo&#39; does not conform to protocol &#39;Foo&#39;</div><div>struct RealFoo : Foo {</div><div>    // Happy</div><div>    func visitValues&lt;T&gt;(throwOnWrongType: Bool, visitors: [(key: String, body: (T) throws -&gt; Void)]) throws {</div><div>        // do stuff...</div><div>    }</div><div><br></div><div>    // error: MyPlayground.playground:23:8: error: type &#39;RealFoo&#39; does not conform to protocol &#39;Foo&#39;</div><div>    //struct RealFoo : Foo {</div><div>    //    ^</div><div>    //</div><div>    //    MyPlayground.playground:16:10: note: candidate has non-matching type &#39;&lt;Self, T&gt; (visitors: [(String, body: (T) throws -&gt; Void)]) throws -&gt; ()&#39; (aka &#39;&lt;τ_0_0, τ_1_0&gt; (visitors: Array&lt;(String, body: (τ_1_0) throws -&gt; ())&gt;) throws -&gt; ()&#39;)</div><div>    //    func visitValues&lt;T&gt;(visitors: [(String, body: (T) throws -&gt; Void)]) throws {</div><div><br></div><div>    // The fix-it suggestion for &quot;error: type &#39;RealFoo&#39; does not conform to protocol &#39;Foo&#39;&quot; inserts the following which makes</div><div>    // the &quot;not conform&quot; error go away however it doesn&#39;t compile because of @escaping</div><div>    // Unhappy</div><div>    // @escaping may only be applied to parameters of function type</div><div>    internal func visitValues&lt;T&gt;(visitors: [(key: String, body: @escaping (T) throws -&gt; Void)]) throws { // NOT PART OF ORIGINAL CODE</div><div>    }</div><div>    // The above shouldn&#39;t be needed since an implementation is provided via an extension on protocol Foo right?</div><div>}</div></div></div><br><div class="gmail_quote"><div dir="ltr">On Wed, Sep 7, 2016 at 8:06 PM Shawn Erickson &lt;<a href="mailto:shawnce@gmail.com">shawnce@gmail.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">To more completely state what I find it a little strange. <div><br></div><div>The default was moved to be non-escaping since that is the better default (for various reason) with @escaping being used to both inform the compiler that something is intentionally escaping (yeah I meant to do that) and to me it seem also helpful as a way to inform the user of the API that the closure they are providing is escaping so they better understand the requirements placed on that closure (e.g. it may not be called before the called function returns, possible retain cycle issues, etc.).</div><div><br></div><div>So when using APIs I would look for @escaping as a way to know I need to think a little more about the behavior of the closure and the func taking the closure that I am calling. If I don&#39;t see it I may incorrectly assume it isn&#39;t escaping when intact it may have be implicitly escaping.</div><div><br></div><div>Anyway my thoughts on this...</div></div><div dir="ltr"><div><br></div><div>-Shawn<br><div><br></div><div><br></div></div></div><br><div class="gmail_quote"><div dir="ltr">On Wed, Sep 7, 2016 at 7:08 PM Shawn Erickson &lt;<a href="mailto:shawnce@gmail.com" target="_blank">shawnce@gmail.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">It just seems a little strange that @escaping only shows up once in the following example (real) function of mine yet both of them are escaping. This fixit message should maybe imply that @escaping isn&#39;t needed since the optional one is already implicitly considered escaping? ...it is kinda confusing when first jumping over to Swift if at one point you are told you need to added @escaping (the non-optional one) yet you are told @escaping isn&#39;t valid for the optional one despite it needing to be escaping (e.g. the fixit doesn&#39;t really explain that is already escaping).<div><br><div><div>    func httpGet&lt;T&gt;(path: String, parameters: [String:String] = [:],</div><div>                    needsAuth: Bool = true, queue: DispatchQueue = DispatchQueue.main,</div><div>                    completion: ObjectFetchCallback&lt;T&gt;?, importer: @escaping HttpImporterCallback&lt;T&gt;)</div></div></div></div><div dir="ltr"><div><div><br></div><div>-Shawn</div></div></div><br><div class="gmail_quote"><div dir="ltr">On Wed, Sep 7, 2016 at 6:51 PM Jacob Bandes-Storch &lt;<a href="mailto:jtbandes@gmail.com" target="_blank">jtbandes@gmail.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div><div><div dir="ltr"><div>On Wed, Sep 7, 2016 at 5:54 PM, Michael Ilseman via swift-users <span dir="ltr">&lt;<a href="mailto:swift-users@swift.org" target="_blank">swift-users@swift.org</a>&gt;</span> wrote:<br></div></div></div></div></div></div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div>I implemented a better (i.e. correct) diagnostic message for this at <a href="https://github.com/apple/swift/pull/4670" target="_blank">https://github.com/apple/swift/pull/4670</a>. I want to also do a better diagnostic specifically for aggregate parameters to functions (e.g. optional closures), but that requires more work in the type checker.</div><div><br></div><div>Basically, @escaping is valid only on closures in function parameter position. The noescape-by-default rule only applies to these closures at function parameter position, otherwise they are escaping. Aggregates, such as enums with associated values (e.g. Optional), tuples, structs, etc., if they have closures, follow the default rules for closures that are not at function parameter position, i.e. they are escaping.</div></div></blockquote><div><br></div></div></div></div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>Shouldn&#39;t it be possible to allow distinguishing @escaping/@noescape for aggregates like these, at least for the simple case of Optional?  (I handled optionals in <a href="https://github.com/apple/swift/pull/4438" target="_blank">https://github.com/apple/swift/pull/4438</a> for imported function types; see <a href="https://github.com/apple/swift/pull/4438#issuecomment-243645367" target="_blank">comment</a>.)</div></div></div></div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><br></div><div>It would be a post-Swift-3 addition to the language to be able to support more robust liveness tracking here. There may be interesting directions to take this, with optional closures being the most common beneficiary. </div><div><div><div><br></div><div><blockquote type="cite"><div>On Sep 7, 2016, at 3:33 PM, Shawn Erickson via swift-users &lt;<a href="mailto:swift-users@swift.org" target="_blank">swift-users@swift.org</a>&gt; wrote:</div><br><div><div dir="ltr">I see <a href="https://bugs.swift.org/browse/SR-2324" target="_blank">https://bugs.swift.org/browse/SR-2324</a> and <a href="https://bugs.swift.org/browse/SR-2444" target="_blank">https://bugs.swift.org/browse/SR-2444</a> which looks related to this issue and may explain the error I saw on &quot;the other side&quot; of this.<div><br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr">On Wed, Sep 7, 2016 at 3:28 PM Shawn Erickson &lt;<a href="mailto:shawnce@gmail.com" target="_blank">shawnce@gmail.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Yeah I actually have a few of those myself that I can no longer do.</div><br><div class="gmail_quote"><div dir="ltr">On Wed, Sep 7, 2016 at 3:26 PM Jon Shier &lt;<a href="mailto:jon@jonshier.com" target="_blank">jon@jonshier.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word">Perhaps relatedly, it no longer seems possible to mark typealiased closures as @escaping. That was quite handy when you know that closures will always be used asynchronously.<div><br></div><div><br></div><div>Jon</div><div><br></div><div><br><div><blockquote type="cite"></blockquote></div></div></div><div style="word-wrap:break-word"><div><div><blockquote type="cite"><div>On Sep 7, 2016, at 6:15 PM, Shawn Erickson via swift-users &lt;<a href="mailto:swift-users@swift.org" target="_blank">swift-users@swift.org</a>&gt; wrote:</div><br></blockquote></div></div></div><div style="word-wrap:break-word"><div><div><blockquote type="cite"><div><div dir="ltr">I should note that this issue also appeared in an earlier variant of Swift after the addition of @escaping but I was on vacation so didn&#39;t get a chance to report it then. It isn&#39;t new with the Xcode 8 GM.<br><br><div class="gmail_quote"><div dir="ltr">On Wed, Sep 7, 2016 at 3:08 PM Shawn Erickson &lt;<a href="mailto:shawnce@gmail.com" target="_blank">shawnce@gmail.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">I like and fully supported the change to @escaping away from @noescape however in a body of code that I am porting to the latest Swift 3 variant (as found in Xcode 8 GM) I am hitting an issue for methods that take an optional completion closure. If optional is involved I can&#39;t find a way to apply @escape to the escaping closure. See the following for an basic example...<div><br></div><div>Is their a way to do what I need and/or is this an edge case in the implementation of @escaping?<br><div><br></div><div><div><font face="monospace" size="1">typealias MyCallback = (String)-&gt;()</font></div><div><font face="monospace" size="1"><br></font></div><div><font face="monospace" size="1">// Happy</font></div><div><font face="monospace" size="1">func foo1(bar: String, completion: ((String)-&gt;())) {</font></div><div><font face="monospace" size="1">    completion(bar)</font></div><div><font face="monospace" size="1">}</font></div><div><font face="monospace" size="1"><br></font></div><div><font face="monospace" size="1">// Happy</font></div><div><font face="monospace" size="1">func foo2(bar: String, completion: MyCallback) {</font></div><div><font face="monospace" size="1">    completion(bar)</font></div><div><font face="monospace" size="1">}</font></div><div><font face="monospace" size="1"><br></font></div><div><font face="monospace" size="1">// Happy</font></div><div><font face="monospace" size="1">func foo3(bar: String, completion: ((String)-&gt;())? = nil) {</font></div><div><font face="monospace" size="1">    completion?(bar)</font></div><div><font face="monospace" size="1">}</font></div><div><font face="monospace" size="1"><br></font></div><div><font face="monospace" size="1">// Happy</font></div><div><font face="monospace" size="1">func foo4(bar: String, completion: MyCallback? = nil) {</font></div><div><font face="monospace" size="1">    completion?(bar)</font></div><div><font face="monospace" size="1">}</font></div><div><font face="monospace" size="1"><br></font></div><div><font face="monospace" size="1">// Happy</font></div><div><font face="monospace" size="1">func foo5(bar: String, completion: Optional&lt;MyCallback&gt; = nil) {</font></div><div><font face="monospace" size="1">    completion?(bar)</font></div><div><font face="monospace" size="1">}</font></div><div><font face="monospace" size="1"><br></font></div><div><font face="monospace" size="1">// Happy</font></div><div><font face="monospace" size="1">func foo6(bar: String, completion: @escaping (String)-&gt;()) {</font></div><div><font face="monospace" size="1">    completion(bar)</font></div><div><font face="monospace" size="1">}</font></div><div><font face="monospace" size="1"><br></font></div><div><font face="monospace" size="1">// Happy</font></div><div><font face="monospace" size="1">func foo7(bar: String, completion: @escaping MyCallback) {</font></div><div><font face="monospace" size="1">    completion(bar)</font></div><div><font face="monospace" size="1">}</font></div><div><font face="monospace" size="1"><br></font></div><div><font face="monospace" size="1">// Unhappy...</font></div><div><font face="monospace" size="1">// &quot;@escaping attribute only applies to function types&quot;</font></div><div><font face="monospace" size="1">func foo8(bar: String, completion: @escaping ((String)-&gt;())? = nil) {</font></div><div><font face="monospace" size="1">    completion?(bar)</font></div><div><font face="monospace" size="1">}</font></div><div><font face="monospace" size="1"><br></font></div><div><font face="monospace" size="1">// Unhappy...</font></div><div><font face="monospace" size="1">// &quot;@escaping attribute only applies to function types&quot;</font></div><div><font face="monospace" size="1">func foo9(bar: String, completion: @escaping MyCallback? = nil) {</font></div><div><font face="monospace" size="1">    completion?(bar)</font></div><div><font face="monospace" size="1">}</font></div><div><font face="monospace" size="1"><br></font></div><div><font face="monospace" size="1">// Unhappy...</font></div><div><font face="monospace" size="1">// &quot;@escaping attribute only applies to function types&quot;</font></div><div><font face="monospace" size="1">func foo10(bar: String, completion: (@escaping ((String)-&gt;()))? = nil) {</font></div><div><font face="monospace" size="1">    completion?(bar)</font></div><div><font face="monospace" size="1">}</font></div><div><font face="monospace" size="1"><br></font></div><div><font face="monospace" size="1">// Unhappy...</font></div><div><font face="monospace" size="1">// &quot;@escaping attribute only applies to function types&quot;</font></div><div><font face="monospace" size="1">func foo11(bar: String, completion: (@escaping MyCallback)? = nil) {</font></div><div><font face="monospace" size="1">    completion?(bar)</font></div><div><font face="monospace" size="1">}</font></div><div><font face="monospace" size="1"><br></font></div><div><font face="monospace" size="1">// Unhappy...</font></div><div><font face="monospace" size="1">// &quot;@escaping attribute only applies to function types&quot;</font></div><div><font face="monospace" size="1">func foo12(bar: String, completion: Optional&lt;@escaping MyCallback&gt; = nil) {</font></div><div><font face="monospace" size="1">    completion?(bar)</font></div><div><font face="monospace" size="1">}</font></div></div></div></div></blockquote></div></div></div></blockquote></div></div></div><div style="word-wrap:break-word"><div><div><blockquote type="cite"><div>
_______________________________________________<br>swift-users mailing list<br><a href="mailto:swift-users@swift.org" target="_blank">swift-users@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-users" target="_blank">https://lists.swift.org/mailman/listinfo/swift-users</a><br></div></blockquote></div><br></div></div></blockquote></div></blockquote></div>
_______________________________________________<br>swift-users mailing list<br><a href="mailto:swift-users@swift.org" target="_blank">swift-users@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-users" target="_blank">https://lists.swift.org/mailman/listinfo/swift-users</a><br></div></blockquote></div><br></div></div></div><br>_______________________________________________<br>
swift-users mailing list<br>
<a href="mailto:swift-users@swift.org" target="_blank">swift-users@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-users" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-users</a><br>
<br></blockquote></div></div></div></blockquote></div></blockquote></div></blockquote></div>