[swift-evolution] [Review] SE-0073: Marking closures as executing exactly once

Gwendal Roué gwendal.roue at gmail.com
Thu May 5 05:27:30 CDT 2016


>> I quite expect being able to throw out of a @noescape(once) block. Maybe the sentence "it must not be executed on any path that throws" should be removed from the proposal, should it have the implications you describe.
>> 
>> Here is below what I expect this proposal to allow. So you see one problematic case?
> 
> Hi Gwendal,
> 
> What about the following case?
> 
> // Function which rethrows closure errors:
> func f1(closure: @noescape(once) () throws -> ()) rethrows {
>  try closure()
> }
> 
> let x: AnyObject
> f1 {
>  if someCondition() { x = MyClass() }
>  if someOtherCondition() { throw MyError.Error() }
>  x = MyOtherClass()
> }
> 
> How do you handle memory management for 'x' on the path that throws?
> If the rule is that upon returning from f1 via a throw the variable
> 'x' should not be initialized, then the closure passed to f1 has to
> guarantee the deinitialization.  But f1 accepts an arbitrary closure.

Hello Dmitri,

To reason about @noescape(once) functions, the easiest way is to replace them with `do`:

    let x: AnyObject
    do {
        if someCondition() { x = MyClass() }
        if someOtherCondition() { throw MyError.error }
        x = MyOtherClass()
    }

This code does not compile because x can't be initialized to MyOtherClass().

But I don't think this is your point. Your point was "how can the compiler handle memory management ?".

I can't answer this question, because I'm not competent enough. But if it can handle the do { … } case, can't it also handle the f { … } case?

Gwendal Roué



More information about the swift-evolution mailing list