[swift-evolution] [Proposal] Make non-escaping closures the default

Brent Royal-Gordon brent at architechies.com
Tue Jun 7 02:45:44 CDT 2016

> This proposal switches the default to be non-escaping and requires an `@escaping` annotation if a closure argument can escape the function body. 

Is @escaping part of the function type syntax (like @autoclosure) or the parameter syntax (like inout)? It seems to me that there are places where you *do* want non-parameter closure variables to be non-escaping:

	func foo(closure: () -> Void) {
		let bar = closure	// You should not be able to escape through `bar`

But then there are also many places where you would have to write @escaping even though a non-escaping closure would be obviously nonsensical:

	struct Foo {
		var closure: () -> Void			// Error; @escaping is mandatory here
		func method() -> () -> Void {...}	// Same

Requiring a boilerplate attribute like this is not really so great.

> Existing code using the `@noescape` attribute will need to be migrated to remove the attribute since it will be the default. In addition, the compiler will need to detect escaping closures that are not marked with `@escaping` and create an error with a fixit to add the required attribute.

This becomes difficult when a protocol has a closure parameter; there's not necessarily a default implementation to examine for escaping, and even if there is one, the default may be a simple, non-escaping implementation for something which ought to allow escaping from other implementations. Similar concerns apply to non-final class members.

One way to address this issue would be to have the migrator conservatively mark non- at noescape closure parameters in protocol and class definitions as @escaping, but that might undermine the intent of automatically transitioning a lot of code to the new default.

(By the way, is an @escaping closure a subtype of a non-escaping closure?)

Brent Royal-Gordon

More information about the swift-evolution mailing list