[swift-evolution] Pitch: only allow capture of inout parameters in @noescape closures

Joe Groff jgroff at apple.com
Thu Jan 28 13:58:56 CST 2016

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:

- Encourage people to write the local copy themselves, if that's what they want:

func foo(inout x: Int) {
  var localX = x; defer { x = localX }

  // Asynchronously mutate localX, then wait for it to finish
  dispatch_async { mutate(&localX) }
  dispatch_sync {}

- You can explicitly capture an immutable copy:

func foo(inout x: Int) {
  // We don't need to mutate or observe mutations on x in the async job
  dispatch_async {[x] in doStuffWithoutMutating(x) }

and/or we could introduce a new explicit capture kind for the current behavior:

func foo(inout x: Int) {
  // Explicitly capture the 'inout' mutable shadow copy of x
  dispatch_async {[inout x] in mutate(&x) }
  dispatch_sync { }

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?

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160128/d58382c9/attachment.html>

More information about the swift-evolution mailing list