[swift-evolution] Pitch: @required attribute for closures

Patrick Pijnappel patrickpijnappel at gmail.com
Sun Jun 5 05:02:29 CDT 2016


This has actually been proposed before, see SE-0073:
https://github.com/apple/swift-evolution/blob/master/proposals/0073-noescape-once.md


On Sun, Jun 5, 2016 at 11:37 AM, Charles Srstka via swift-evolution <
swift-evolution at 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 at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160605/11e6e266/attachment.html>


More information about the swift-evolution mailing list