<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">I think the time has come for us to limit the implicit capture of 'inout' parameters to @noescape closures. In the early days before @noescape, we designed a semantics for capturing "inout" parameters that attempted to balance the constraints on inout with the usability of higher-order functions. Inout parameters don't pass a first-class reference as in other languages, but instead provide a limited lease to mutate a property for the duration of a call; this means closures can't extend the lifetime of that lease, so closures instead capture the local mutable copy of the inout parameter. This gives the expected behavior as long as closures over an inout parameter never escape their original scope, but leads to surprises as soon as those closures escape. This unintuitive behavior has made several "Swift gotchas" lists. Now that we can explicitly mark closures as not escaping, I think we should prevent 'inout' parameters from being implicitly captured by escapable closures. There are several ways we can still support today's behavior:<div class=""><br class=""></div><div class="">- Encourage people to write the local copy themselves, if that's what they want:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">func foo(inout x: Int) {</div><div class=""> var localX = x; defer { x = localX }</div><div class=""><br class=""></div><div class=""> // Asynchronously mutate localX, then wait for it to finish</div><div class=""> dispatch_async { mutate(&localX) }</div><div class=""> dispatch_sync {}</div><div class="">}</div><div class=""><br class=""></div></blockquote>- You can explicitly capture an immutable copy:<div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class="">func foo(inout x: Int) {</div><div class=""> // We don't need to mutate or observe mutations on x in the async job</div><div class=""> dispatch_async {[x] in doStuffWithoutMutating(x) }</div><div class="">}</div><div class=""><br class=""></div></blockquote>and/or we could introduce a new explicit capture kind for the current behavior:<div class=""><div class=""><br class=""></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class="">func foo(inout x: Int) {</div></div><div class=""><div class=""> // Explicitly capture the 'inout' mutable shadow copy of x</div></div><div class=""><div class=""> dispatch_async {[inout x] in mutate(&x) }</div></div><div class=""> dispatch_sync { }</div><div class=""><div class="">}</div></div></blockquote><div class=""><br class=""></div><div class="">Making it explicit should make the behavior less surprising when it occurs. We should able to provide fixits to migrate code that relies on the current behavior as well. What do you all think?</div><div class=""><br class=""></div><div class="">-Joe</div></body></html>