[swift-users] Compiler refuses non-escaping closure calls in nested function
Jean-Denis Muys
jdmuys at gmail.com
Mon Oct 10 09:04:44 CDT 2016
Thanks Ole,
You are perfectly right regarding the error message. For some reason, I misread it. I am sorry about that.
The actual error message, as you point out, makes much more sense!
The rest of your explanation makes sense too, except:
When I declare my closure as @noescape, (the default), I explicitly tell the compiler that, despite the fact closing over it *may* allow it to escape, I, the programmer, guarantee that it will not.
I would understand a warning, but I don’t understand that the compiler insists on putting out an error.
So, while the compiler could perhaps, as you say, perform more sophisticated checks, I don’t even request that. I request however, to be able to tell the compiler that I know better.
If I am wrong, and if I still let the closure escape despite my promise, then I made a programming error, and my code can legitimately crash.
This is no different than using the “!” to promise the compiler that an optional is not nil: if I don’t keep my promise, the program crashes.
Last, in presence of a similar warning (instead of an error), a simple way to squelch the warning would be to make the @noescape declaration explicit.
This would require un-deprecating it.
I now feel that I should propose that as an evolution.
What do you think?
Jean-Denis
> On 10 Oct 2016, at 12:52, Ole Begemann <ole at oleb.net> wrote:
>
>> 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20161010/72fec6ab/attachment.html>
More information about the swift-users
mailing list