Let's get more technical on the original proposal.
All non-function arguments can be treated as "escaping" as there is no way to express non-escaping behavior for them. But the introduction of the explicit @escaping
attribute would imply that there should be @noescape
as well.
What would @noescape
mean for non-function arguments?
Escaping function type supports not very many operations on it: own it, lose it, pass it as an escaping or non-escaping argument, and call it. Making it non-escaping denies owning and passing it as an escaping argument. This also implies that the context is either not exists or is unowned by the callee.
So, a non-escaping argument should follow the following rules:
- It's unowned. The lifetime during the invocation is guaranteed by the caller. This is opposed to the borrow/consume semantics.
- It cannot be owned.
- It cannot participate in operations that may allow it to escape.
And an escaping argument is just a regular argument just like all of them now.
But for non-escaping arguments to be any useful we should also provide a way to specify that functions operating on self
do not allow self
to escape. Something similar to the borrowing
/consuming
keywords in front of a function.
class Foo {
private var _isGood = true
nonescaping var isGood: Bool { _isGood }
}
func bar(foo: @noescape Foo) {
if foo.isGood { // call is allowed because it's marked as `nonescaping`
print("good")
}
}