[Accepted] SE-0103: Make non-escaping closures the default

Proposal link: swift-evolution/0103-make-noescape-default.md at master · apple/swift-evolution · GitHub

Hello Swift Community,

The review of "SE-0103: Make non-escaping closures the default" ran from June 21...27. The proposal is *accepted* for Swift 3 with a minor revision: instead of a “asUnsafeEscapingClosure(_:)" function that removes the @escaping attribute, the core team prefers a function with this signature (roughly) like:

  func withoutActuallyEscaping<ClosureType, ResultType>(_ closure: ClosureType, do: (fn : @escaping ClosureType) -> ResultType) -> ResultType { … }

This allows one to safely add the @escaping attribute in situations where a closure is known not to actually escape. For example, in a situation where you might want to use a lazy algorithm, you could use:

  func yourFunction(fn : (Int) -> Int) { // fn defaults to non-escaping.
    withoutActuallyEscaping(fn) { fn in // fn is now marked @escaping inside the closure
      ... somearray.lazy.map(fn) … // pass fn to something that is notationally @escaping
    }
  }

The key to this approach is that the “withoutActuallyEscaping” function can verify that the closure has not actually escaped when it completes, providing a safe model for locally adding the @escaping attribute when needed. The core team believes that the actual implementation of withoutActuallyEscaping will require some magic, but that it should be implementable.

Many thanks to Trent Nadeau for driving this proposal forward. I filed SR-1952 to track implementation of this feature.

-Chris Lattner
Review Manager