# Allowing @escaping for optional closures in method signature

**URL:** <https://forums.swift.org/t/allowing-escaping-for-optional-closures-in-method-signature/27556>\
**Category:** Pitches\
**Created:** [August 2, 2019, 1:42pm UTC](https://forums.swift.org/t/allowing-escaping-for-optional-closures-in-method-signature/27556 "2019-08-02T13:42:47Z")\
**Posts on this page:** 17\
**Page:** 2

<div class="post-metadata">

**Author:** ![sveinhal](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/sveinhal/32/3992_2.png) [@sveinhal](https://forums.swift.org/u/sveinhal)\
**Post date:** [August 2, 2019, 4:39pm UTC](https://forums.swift.org/t/allowing-escaping-for-optional-closures-in-method-signature/27556/21 "2019-08-02T16:39:33Z")

</div>

All optional closures must be escaping, since the closure is stored inside the `Optional.some` case.

One could argue that it might sometimes be beneficial to be able to mark such closures as _non-escaping_. However, that would require some kind of language support to mark `Optional` as escaping/nonescaping too, or somehow add some sort of compiler magic to infer wether or not the optional that is contaning the nonescaping closure will actually outlive the caller.

This seems very non-trivial to me, but what do I know?

However, short answer is: The closure must be escaping, so no need to explicitly mark it. The same goes for instance members, etc.

---

<div class="post-metadata">

**Author:** ![Lantua](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lantua/32/8868_2.png) [@Lantua](https://forums.swift.org/u/Lantua)\
**Post date:** [August 2, 2019, 4:43pm UTC](https://forums.swift.org/t/allowing-escaping-for-optional-closures-in-method-signature/27556/22 "2019-08-02T16:43:20Z")

</div>

@GLanza I see. I probably read a little too fast, my bad 😛.

I do like @glessard suggestion (and was about to suggest it myself if he hasn't).

To add on what others said, that it's non-trivial to add it; we don't want `Optional` to be special. Sure, it does have proliferated amount of sugar, but it usually ends up being normal `enum` with 2 cases. If we want non-escaping closure in `Optional`, we'd want to support it on everything else, say `Foo`. To make anything non-escaping, we'd need its container to be non-escaping as well, which means we want non-escaping variables.

There could definitely be a better way, but I think that's how we're likely gonna end up if we really want this feature.

---

<div class="post-metadata">

**Author:** ![GetSwifty](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/getswifty/32/39108_2.png) [@GetSwifty](https://forums.swift.org/u/GetSwifty)\
**Post date:** [August 2, 2019, 4:51pm UTC](https://forums.swift.org/t/allowing-escaping-for-optional-closures-in-method-signature/27556/23 "2019-08-02T16:51:19Z")

</div>

> [@GLanza](#):
>
> func foo(completion: @escaping ((Bool) -\> Void)? = nil)

I think this makes sense to add, but flipped from the OP.

I would say the spelling should be:

```swift
func foo(completion: (@nonEscaping (Bool) -> Void)? = nil)

```

This fixes some problems.

1. Rather than putting the annotation on the Optional, `@nonEscaping Optional<() -> ()>`, it put it on the generic Type of the optional: `Optional<@nonEscaping () -> ()>`. I'm not sure how Functions are designed internally, but I would imagine that simplifies the implementation. Rather than allowing something to be added to an Optional-if-the-optional-is-a-function, just support it as a general annotation for functions.
2. There should be no source compatibility issues. It's an additive change that doesn't change any existing `Types`
3. If desired, supporting both `@escaping` and `@nonEscaping` to any function _could_ be supported with no compatibility issues, and left up to the user what they want to make explicit.

---

<div class="post-metadata">

**Author:** ![GLanza](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/glanza/32/3827_2.png) [@GLanza](https://forums.swift.org/u/GLanza)\
**Post date:** [August 2, 2019, 5:10pm UTC](https://forums.swift.org/t/allowing-escaping-for-optional-closures-in-method-signature/27556/24 "2019-08-02T17:10:03Z")

</div>

> [@Lantua](#):
>
> To add on what others said, that it's non-trivial to add it; we don't want `Optional` to be special. Sure, it does have proliferated amount of sugar, but it usually ends up being normal `enum` with 2 cases. If we want non-escaping closure in `Optional` , we'd want to support it on everything else, say `Foo` . To make anything non-escaping, we'd need its container to be non-escaping as well, which means we want non-escaping variables.
> 
> There could definitely be a better way, but I think that's how we're likely gonna end up if we really want this feature.

The problem about the default empty closure is about how clean the method signature would look like.

`func foo(completion: @escaping (Data?, URLResponse?, Error?) -> Void = { _, _, _ in })`  
or  
`func foo(completion: (Data?, URLResponse?, Error?) -> Void = { _, _, _ in })`

is not pretty.

Maybe something like  
`func foo(completion: @escaping (Data?, URLResponse?, Error?) -> Void = Empty)` ??

Don't know if it's feasible toh.

---

<div class="post-metadata">

**Author:** ![griotspeak](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/griotspeak/32/1966_2.png) [@griotspeak](https://forums.swift.org/u/griotspeak)\
**Post date:** [August 2, 2019, 5:26pm UTC](https://forums.swift.org/t/allowing-escaping-for-optional-closures-in-method-signature/27556/25 "2019-08-02T17:26:44Z")

</div>

How much would it cost to extend the idea of escaping to every input? To know that an option closure was non-escaping, you'd have to track the enum (`Optional`) input and then use knowledge that it wouldn't escape to conclude that the closure inside it doesn't.

---

<div class="post-metadata">

**Author:** ![glessard](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/glessard/32/409_2.png) [@glessard](https://forums.swift.org/u/glessard)\
**Post date:** [August 2, 2019, 6:22pm UTC](https://forums.swift.org/t/allowing-escaping-for-optional-closures-in-method-signature/27556/26 "2019-08-02T18:22:12Z")

</div>

> [@GetSwifty](#):
>
> I would say the spelling should be:
> 
> ```swift
> func foo(completion: (@nonEscaping (Bool) -> Void)? = nil)
> 
> ```

As long as the parameter is copyable, all of its properties are escaping. The only way to make this work is to have a special type of `Optional` that is non-copyable, and use it as the parameter type.

---

<div class="post-metadata">

**Author:** ![GetSwifty](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/getswifty/32/39108_2.png) [@GetSwifty](https://forums.swift.org/u/GetSwifty)\
**Post date:** [August 2, 2019, 6:35pm UTC](https://forums.swift.org/t/allowing-escaping-for-optional-closures-in-method-signature/27556/27 "2019-08-02T18:35:00Z")

</div>

Fair point. Some additional rules would then have to be written around it, but I believe it could still be called without copying:

```swift
func foo(completion: (@nonEscaping (Bool) -> Void)? = nil) {
    completion?()
}

```

Unless the unwrap operation is copying the variable internally, (which I don't know), Is there a reason the same rules can't be applied as a typical non-escaping parameter? Are the mechanisms I'm unaware of to indicate that a general parameter can't be copied? If not I can imagine that being something that could/should be added to the language generally.

---

<div class="post-metadata">

**Author:** ![glessard](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/glessard/32/409_2.png) [@glessard](https://forums.swift.org/u/glessard)\
**Post date:** [August 2, 2019, 8:16pm UTC](https://forums.swift.org/t/allowing-escaping-for-optional-closures-in-method-signature/27556/28 "2019-08-02T20:16:40Z")

</div>

> [@GLanza](#):
>
> Maybe something like  
> `func foo(completion: @escaping (Data?, URLResponse?, Error?) -> Void = Empty)` ??

```swift
func empty(data: Data?, response: URLResponse?, error: Error?) {}
func foo(completion: @escaping (Data?, URLResponse?, Error?) -> Void = empty) {}

```

---

<div class="post-metadata">

**Author:** ![GLanza](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/glanza/32/3827_2.png) [@GLanza](https://forums.swift.org/u/GLanza)\
**Post date:** [August 2, 2019, 9:34pm UTC](https://forums.swift.org/t/allowing-escaping-for-optional-closures-in-method-signature/27556/29 "2019-08-02T21:34:29Z")

</div>

> [@glessard](#):
>
> ```swift
> func empty(data: Data?, response: URLResponse?, error: Error?) {}
> func foo(completion: @escaping (Data?, URLResponse?, Error?) -> Void = empty) {}
> 
> ```

The point is that I don't want to write an "empty" function for each block I might want to be optional, just for the sake of having a prettier method signature. I was wondering if it's possible and appreciated something synthesised by the compiler, and maybe even checkable like `completion.isEmpty` I have no idea if it's doable. 😄

---

<div class="post-metadata">

**Author:** ![GLanza](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/glanza/32/3827_2.png) [@GLanza](https://forums.swift.org/u/GLanza)\
**Post date:** [August 2, 2019, 9:38pm UTC](https://forums.swift.org/t/allowing-escaping-for-optional-closures-in-method-signature/27556/30 "2019-08-02T21:38:10Z")

</div>

basically  
`func foo(completion: @escaping (Data?, URLResponse?, Error?) -> Void = empty)`  
would be equivalent to  
`func foo(completion: @escaping (Data?, URLResponse?, Error?) -> Void = {_, _, _ in })`

with corresponding non escaping ones:

```swift
func foo(completion: (Data?, URLResponse?, Error?) -> Void = empty)
func foo(completion: (Data?, URLResponse?, Error?) -> Void = {_, _, _ in })

```

This way there is no ambiguity around which is actually escaping.

---

<div class="post-metadata">

**Author:** ![glessard](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/glessard/32/409_2.png) [@glessard](https://forums.swift.org/u/glessard)\
**Post date:** [August 2, 2019, 10:10pm UTC](https://forums.swift.org/t/allowing-escaping-for-optional-closures-in-method-signature/27556/31 "2019-08-02T22:10:27Z")

</div>

For what it's worth, I would really like to get implicitly-ignored arguments back for empty closures. Then a pretty good option would be thus:

```swift
func foo(completion: (Data?, URLResponse?, Error?) -> Void = {})

```

---

<div class="post-metadata">

**Author:** ![GetSwifty](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/getswifty/32/39108_2.png) [@GetSwifty](https://forums.swift.org/u/GetSwifty)\
**Post date:** [August 2, 2019, 10:23pm UTC](https://forums.swift.org/t/allowing-escaping-for-optional-closures-in-method-signature/27556/32 "2019-08-02T22:23:24Z")

</div>

FWIW, a `typealias` can at least smooth out the declaration.

```swift
typealias FooCompletion = (Data?, URLResponse?, Error?) -> ()

func foo(completion: FooCompletion = {_, _, _ in }) {

}

```

---

<div class="post-metadata">

**Author:** ![GLanza](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/glanza/32/3827_2.png) [@GLanza](https://forums.swift.org/u/GLanza)\
**Post date:** [August 3, 2019, 8:29am UTC](https://forums.swift.org/t/allowing-escaping-for-optional-closures-in-method-signature/27556/33 "2019-08-03T08:29:21Z")

</div>

I'll open another pitch with a better intention definition

---

<div class="post-metadata">

**Author:** ![GLanza](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/glanza/32/3827_2.png) [@GLanza](https://forums.swift.org/u/GLanza)\
**Post date:** [August 4, 2019, 10:15am UTC](https://forums.swift.org/t/allowing-escaping-for-optional-closures-in-method-signature/27556/34 "2019-08-04T10:15:12Z")

</div>

continues on [@unrequired in function signature for optional closure parameters](https://forums.swift.org/t/pitch-unrequired-closure-parameters/27577) here I explained a bit better the reasons of this "request".

---

<div class="post-metadata">

**Author:** ![GLanza](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/glanza/32/3827_2.png) [@GLanza](https://forums.swift.org/u/GLanza)\
**Post date:** [August 14, 2019, 10:15am UTC](https://forums.swift.org/t/allowing-escaping-for-optional-closures-in-method-signature/27556/35 "2019-08-14T10:15:39Z")

</div>

Due to [new informations](https://forums.swift.org/t/unrequired-in-function-signature-for-optional-closure-parameters/27577/48) I think we can continue this conversation.

@John_McCall said:

> It should be quite straightforward to extend escape analysis to optional parameter functions and allow them to be explicitly marked as `@escaping` or `@nonEscaping` (or however we want to spell that). We can also investigate changing the _default_ language rule for optional parameter functions so that it's consistent for different optionalities, but that's a separable question.

So, the take away from that parallel pitch is that we **can** teach the compiler to understand that optional values can propagate escapability.

I updated the original post with the new info.

---

<div class="post-metadata">

**Author:** ![GLanza](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/glanza/32/3827_2.png) [@GLanza](https://forums.swift.org/u/GLanza)\
**Post date:** [August 20, 2019, 11:31am UTC](https://forums.swift.org/t/allowing-escaping-for-optional-closures-in-method-signature/27556/36 "2019-08-20T11:31:24Z")

</div>

Keeping the ball rolling: We learned that optional can, with some work, propagate closures escapability.  
We have at the moment two options (apart from the obvious third one of doing nothing).

_Poll ([view on site](https://forums.swift.org/t/allowing-escaping-for-optional-closures-in-method-signature/27556/36))_

My personal preference would be for the second one, having uniform closure escapability handling, but I understand that it is unclear wether or not changing default for Optional closure would break ABI stability. It's something to be investigated.

Let me know your preference, please. And thank you all. 🙂

---

<div class="post-metadata">

**Author:** ![GLanza](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/glanza/32/3827_2.png) [@GLanza](https://forums.swift.org/u/GLanza)\
**Post date:** [August 20, 2019, 9:03pm UTC](https://forums.swift.org/t/allowing-escaping-for-optional-closures-in-method-signature/27556/37 "2019-08-20T21:03:50Z")

</div>

I didn't write it explicitly, but the option "change the default of optional closures to be nonescaping" assumes that then you can mark as @escaping Optional closures just like you do with simple closures. 🙂

[Previous page](https://forums.swift.org/t/allowing-escaping-for-optional-closures-in-method-signature/27556.md?page=1)
