Sent from my iPad

> On Jun 5, 2016, at 6:56 AM, Andrew Bennett <cac...@gmail.com> wrote:
> 
> I like this.
> 
> One of the suggestions on @noescape(once) was that it just becomes @once and 
> works with escaping closures too. It might be possible if compile time checks 
> verified that the closure isn't copied, and that it is called before being 
> deinit-ialized. Failing that I'm happy with a runtime circumstance in the 
> cases the compiler can't check.

Yeah, maybe if it is only used asynchronously and never stored in a member or 
global it could be verified and that is a pretty common case.  That would 
certainly be easier than the general case.

I prefer @once over @required if the guarantee is single execution.  If the 
guarantee is *at least once* obviously @once is not the right attribute, but 
I'm not convinced @required is either.  Maybe @invoked.

> 
> It would be great if @required took into the account the feedback from that 
> proposal and considered the synchronous case too.
> 
> As an aside, you can get some of the guarantees you want like this:
> 
> func doSomething(completionHandler: (SomeEnum) -> ()) {
>   dispatch_async(someQueue) {
>     let result: SomeEnum
>     // the compiler ensures 'result' is set
>     defer { completionHandler(result) }
> 
>     if aCondition {
>       if bCondition {
>         result = .Foo
>       } else {
>         result = .Bar
>       }
>       // the compiler ensures you do this, because it is 'let'
>       return
>     }
> 
>     if cCondition {
>       result = .Baz
>     }
>   }
> }
> 
>> On Sun, Jun 5, 2016 at 9:42 PM, Matthew Johnson via swift-evolution 
>> <swift-evolution@swift.org> wrote:
>> 
>> 
>> Sent from my iPad
>> 
>>> On Jun 5, 2016, at 5:02 AM, Patrick Pijnappel via swift-evolution 
>>> <swift-evolution@swift.org> wrote:
>>> 
>>> This has actually been proposed before, see SE-0073: 
>>> https://github.com/apple/swift-evolution/blob/master/proposals/0073-noescape-once.md
>> 
>> Actually that proposal was for noescape closures and this suggestion is for 
>> escaping closures.  I don't think the compiler can verify this for noescape 
>> closures.  If it is possible it would be far more complicated.
>> 
>>> 
>>> 
>>>> On Sun, Jun 5, 2016 at 11:37 AM, Charles Srstka via swift-evolution 
>>>> <swift-evolution@swift.org> wrote:
>>>> MOTIVATION:
>>>> 
>>>> As per the current situation, there is a pitfall when writing asynchronous 
>>>> APIs that does not occur when writing synchronous APIs. Consider the 
>>>> following synchronous API:
>>>> 
>>>> func doSomething() -> SomeEnum {
>>>>         if aCondition {
>>>>                 if bCondition {
>>>>                         return .Foo
>>>>                 } else {
>>>>                         return .Bar
>>>>                 }
>>>>         } else {
>>>>                 if cCondition {
>>>>                         return .Baz
>>>>                 }
>>>>         }
>>>> }
>>>> 
>>>> The compiler will give an error here, since if both aCondition and 
>>>> cCondition are false, the function will not return anything.
>>>> 
>>>> However, consider the equivalent async API:
>>>> 
>>>> func doSomething(completionHandler: (SomeEnum) -> ()) {
>>>>         dispatch_async(someQueue) {
>>>>                 if aCondition {
>>>>                         if bCondition {
>>>>                                 completionHandler(.Foo)
>>>>                         } else {
>>>>                                 completionHandler(.Bar)
>>>>                         }
>>>>                 } else {
>>>>                         if cCondition {
>>>>                                 completionHandler(.Baz)
>>>>                         }
>>>>                 }
>>>>         }
>>>> }
>>>> 
>>>> Whoops, now the function can return without ever firing its completion 
>>>> handler, and the problem might not be discovered until runtime (and, 
>>>> depending on the complexity of the function, may be hard to find).
>>>> 
>>>> PROPOSED SOLUTION:
>>>> 
>>>> Add a @required attribute that can be applied to closure arguments. This 
>>>> attribute simply states that the given closure will always be eventually 
>>>> called, and the compiler can enforce this.
>>>> 
>>>> DETAILED DESIGN:
>>>> 
>>>> - The @required attribute states in our API contract that a given closure 
>>>> *must* be called at some point after the function is called.
>>>> 
>>>> - Standard API calls like dispatch_async that contractually promise to 
>>>> execute a closure or block get @required added to their signatures.
>>>> 
>>>> - When the compiler sees a @required closure in a function declaration, it 
>>>> checks to make sure that every execution path either calls the closure at 
>>>> some point, or sends a @required closure to another API that eventually 
>>>> ends up calling the closure.
>>>> 
>>>> - If there’s a way for a @required closure not to be called, the compiler 
>>>> emits an error letting the developer know about the bug in his/her code.
>>>> 
>>>> IMPACT ON EXISTING CODE:
>>>> 
>>>> None. This is purely additive.
>>>> 
>>>> ALTERNATIVES CONSIDERED:
>>>> 
>>>> I got nothin’.
>>>> 
>>>> Charles
>>>> 
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> swift-evolution@swift.org
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution@swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to