[swift-evolution] [Pitch] Move @noescape

Brent Royal-Gordon brent at architechies.com
Fri Mar 4 23:32:43 CST 2016

>> My feeling is that we should only attach information to the *type* if it follows the value around and if, at least in principle, it would make sense in at least some other type-like contexts. 
> I think it does, and let me illustrate why.  Consider an autoclosure-taking function like this (one silly example):
> 	func f(@autoclosure a : () -> ()) {}
> You can use it as you’d expect, e.g.:
> 	f(print("hello”))
> Of course, f is a first class value, and you can assign it:
> 	let x = f
> 	x(print("hello"))
> This works, because x has type "(@autoclosure () -> ()) -> ()”.  You can see this if you force a type error:
> 	let y : Int = x
> 	// error: cannot convert value of type '(@autoclosure () -> ()) -> ()' to specified type 'Int'
> However, you can’t write this out explicitly:
> 	let x2 : (@autoclosure () -> ()) -> () = f
> 	// error: attribute can only be applied to declarations, not types
> This seems dumb to me :-) you should be able to write the type for any declaration you can produce.  Once you do that, it makes sense to spell the original function as:
> 	func f(a : @autoclosure () -> ()) {}
> for consistency.  Yes, I totally get the irony of the fact that @autoclosure used to be on the type in swift 1.

How much sense does it really make to have a closure with an @autoclosure parameter, though? @autoclosure is meant to be syntactic sugar for when a function needs to control the evaluation of its parameters, like `&&` or `Result(try something())`. Does that feature make sense for closures? Even if it does, does it make sense for there to be a type error when you pass a `Foo -> Bar` where an `@autoclosure Foo -> Bar` is expected, or vice versa?

I think it might make more sense to think of your `f` as having the type `(() -> ()) -> Void` and have the @autoclosure-ness of particular parameters be something that's attached to `f` itself, not the function inside it. Just as a function's access level or @objc-ness isn't part of its type, nor is the @autoclosure-ness of its parameters.

Even if we decide we have to support @autoclosure on closures, if we turn parameter labels into a feature of the variable's name instead of its type (which I believe I've seen discussed), we will have an opportunity to specify that:

	let x2(@autoclosure _:): (() -> ()) -> () = f		// no parameter label
	let x2(@autoclosure x:): (() -> ()) -> () = f		// adding a parameter label

Or you could just shed the autoclosure-ness of the parameter by writing any of these:

	let x2 = f									// inferring the type
	let x2: (() -> ()) -> () = f						// stating it explicitly
	let x2(x:): (() -> ()) -> () = f					// adding a parameter label

Brent Royal-Gordon

More information about the swift-evolution mailing list