[swift-users] Compiler refuses non-escaping closure calls in nested function
Ole Begemann
ole at oleb.net
Mon Oct 10 05:52:03 CDT 2016
> The line "let result = closure(n)" is refused by the compiler with the
> error message "declaration over non closing parameter may allow it to
> escape".
>
> First off, while I know what an escaping or a non-escaping closure is, I
> find this error message utterly impossible to understand. To begin with,
> the sentence "non closing parameter" is meaningless to me.
The error message I'm seeing in Xcode 8.0 is "Declaration closing over
*non-escaping* parameter 'closure' may allow it to escape", so I don't
know where you're seeing the "non closing parameter". And "non-escaping
parameter" does make a lot more sense, I think.
> In any case, my main function is passed a non-escaping closure. I want
> to call it from inside it, the compiler is ok with. I want also to call
> it from a nested function, but the compiler disagrees.
>
> I believe the compiler should not complain here. Did I miss anything?
I think the error message is actually quite good, given that the
compiler apparently is taking some shortcuts to prove that a parameter
doesn't escape.
By declaring a function that closes over the non-escaping parameter,
you're creating a situation that *may* allow the non-escaping closure to
escape, i.e. the compiler can't guarantee anymore that it won't escape.
For example, you could do assign the `closureDoubled` function to a
variable that's outside the scope of `mainFunction`:
// Variable outside the scope of mainFunction
var f: (Int) -> (Int) = { $0 }
func mainFunction(closure: (Int) -> Int) -> Int {
func closureDoubled(_ n: Int) -> Int {
let result = closure(n)
return 2*result
}
// closure would escape here
f = closureDoubled
...
}
mainFunction { $0 }
f(5)
If this were allowed, `closure` would be able to escape. I think this
possibility explains the error message.
Now the compiler *could* of course check for this and I think you're
right in arguing that it *should* ideally perform more sophisticated
checks, but since it currently seems to be taking some shortcuts in
guaranteeing that a parameter doesn't escape, it has to disallow
anything it can't verify as correct.
Ole
More information about the swift-users
mailing list