# SE-0326: Multi-statement closure parameter/result type inference

**URL:** <https://forums.swift.org/t/se-0326-multi-statement-closure-parameter-result-type-inference/52964>\
**Category:** Proposal Reviews\
**Created:** [October 21, 2021, 9:15pm UTC](https://forums.swift.org/t/se-0326-multi-statement-closure-parameter-result-type-inference/52964 "2021-10-21T21:15:25Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![ben-cohen](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ben-cohen/32/296_2.png) [@ben-cohen](https://forums.swift.org/u/ben-cohen)\
**Post date:** [October 21, 2021, 9:15pm UTC](https://forums.swift.org/t/se-0326-multi-statement-closure-parameter-result-type-inference/52964/1 "2021-10-21T21:15:25Z")

</div>

Hello, Swift community.

The review of [SE-0326: Multi-statement closure parameter/result type inference](https://github.com/apple/swift-evolution/blob/main/proposals/0326-extending-multi-statement-closure-inference.md) begins now and runs through November 1, 2021.

Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to the [review manager](mailto:ben_cohen@apple.com). If you do email me directly, please put "SE-0302" somewhere in the subject line.

## What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

- What is your evaluation of the proposal?
- Is the problem being addressed significant enough to warrant a change to Swift?
- Does this proposal fit well with the feel and direction of Swift?
- If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
- How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

More information about the Swift evolution process is available at:

> [https://github.com/apple/swift-evolution/blob/master/process.md](https://github.com/apple/swift-evolution/blob/master/process.md)

As always, thank you for contributing to Swift.

Ben Cohen  
Review Manager

---

<div class="post-metadata">

**Author:** ![Nobody1707](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nobody1707/32/2169_2.png) [@Nobody1707](https://forums.swift.org/u/Nobody1707)\
**Post date:** [October 21, 2021, 10:20pm UTC](https://forums.swift.org/t/se-0326-multi-statement-closure-parameter-result-type-inference/52964/2 "2021-10-21T22:20:26Z")

</div>

> [@ben-cohen](#):
>
> - What is your evaluation of the proposal?

+1

> [@ben-cohen](#):
>
> - Is the problem being addressed significant enough to warrant a change to Swift?

Absolutely.

> [@ben-cohen](#):
>
> - Does this proposal fit well with the feel and direction of Swift?

Definitely.

> [@ben-cohen](#):
>
> - If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

This is similar to how C++ type checks auto return types in functions and lambdas. I think this is a good fit for Swift, but I am very interested in whether the return type joining idea is feasable.

> [@ben-cohen](#):
>
> - How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

I read the entire proposal and the pitch thread.

---

<div class="post-metadata">

**Author:** ![stevapple](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/stevapple/32/31979_2.png) [@stevapple](https://forums.swift.org/u/stevapple)\
**Post date:** [October 22, 2021, 5:06am UTC](https://forums.swift.org/t/se-0326-multi-statement-closure-parameter-result-type-inference/52964/3 "2021-10-22T05:06:18Z")

</div>

@ben-cohen Looks like the thread title is wrong. Can you change it?

---

<div class="post-metadata">

**Author:** ![mrwerdo](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mrwerdo/32/12207_2.png) [@mrwerdo](https://forums.swift.org/u/mrwerdo)\
**Post date:** [October 22, 2021, 10:56am UTC](https://forums.swift.org/t/se-0326-multi-statement-closure-parameter-result-type-inference/52964/4 "2021-10-22T10:56:25Z")

</div>

I’m confused about the motivation example. Is it supposed to compile correctly without the proposed changes?

Particularly, the map function is supposed to return a type `T` that conforms to `BinaryInteger`. However `Void`, the return type of `doSomething`, does not conform to `BinaryInteger`.

It seems to me that there is no correct way to type check the first example. Perhaps `doSomething` should return a type that conforms to `BinaryInteger`?

I’ve spent about 20 minutes reading the motivation section of the proposal so maybe I am misunderstanding what the example is supposed to illustrate.

---

<div class="post-metadata">

**Author:** ![xedin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/xedin/32/309_2.png) [@xedin](https://forums.swift.org/u/xedin)\
**Post date:** [October 22, 2021, 4:05pm UTC](https://forums.swift.org/t/se-0326-multi-statement-closure-parameter-result-type-inference/52964/5 "2021-10-22T16:05:59Z")

</div>

Sorry for the confusion, `map` in that example shouldn’t have a `BinaryInteger` requirement on `T`, I will fix it momentarily. Pitch had `doSomething` return `U` but it was mentioned that it’s not very clear because result type would change in multi-statement case, so I changed it to `Void` instead.

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [October 22, 2021, 4:13pm UTC](https://forums.swift.org/t/se-0326-multi-statement-closure-parameter-result-type-inference/52964/6 "2021-10-22T16:13:01Z")

</div>

The **Source compatibility** section is a bit confusing to me. It ends:

> There are a couple of ways to mitigate situations like this: [...]

However, it's not clear to me which of the subsequently listed options the proposal actually adopts. Is the behavior adopted by this proposal source-compatible, or not?

---

<div class="post-metadata">

**Author:** ![benrimmington](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/benrimmington/32/695_2.png) [@benrimmington](https://forums.swift.org/u/benrimmington)\
**Post date:** [October 22, 2021, 4:26pm UTC](https://forums.swift.org/t/se-0326-multi-statement-closure-parameter-result-type-inference/52964/7 "2021-10-22T16:26:28Z")

</div>

_§Motivation_ and _§Detailed design_ both have:

```swift
  logger.info("About to call 'doSomething(\$0)'")

```

The `(\$0)` almost looks like an interpolation, but that would change the "first reference to an anonymous parameter" location. It might be clearer to remove the `(\$0)` from those examples.

---

<div class="post-metadata">

**Author:** ![xedin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/xedin/32/309_2.png) [@xedin](https://forums.swift.org/u/xedin)\
**Post date:** [October 22, 2021, 4:37pm UTC](https://forums.swift.org/t/se-0326-multi-statement-closure-parameter-result-type-inference/52964/8 "2021-10-22T16:37:40Z")

</div>

Fixed by [[SE-0326] Fix an example in the `Motivation` section by xedin · Pull Request #1465 · apple/swift-evolution · GitHub](https://github.com/apple/swift-evolution/pull/1465).

---

<div class="post-metadata">

**Author:** ![xedin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/xedin/32/309_2.png) [@xedin](https://forums.swift.org/u/xedin)\
**Post date:** [October 22, 2021, 4:40pm UTC](https://forums.swift.org/t/se-0326-multi-statement-closure-parameter-result-type-inference/52964/9 "2021-10-22T16:40:23Z")

</div>

No, the proposal doesn't adopt any mitigations for the problem, it let's these calls be ambiguous and leaves it for the developers to fix it by providing explicit type.

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [October 22, 2021, 6:06pm UTC](https://forums.swift.org/t/se-0326-multi-statement-closure-parameter-result-type-inference/52964/10 "2021-10-22T18:06:58Z")

</div>

In that case, has there been an investigation to what the source compatibility impact of this change is, in practice? Were there any issues in the source compat test suite, or do we expect this situation to be exceedingly rare?

---

<div class="post-metadata">

**Author:** ![xedin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/xedin/32/309_2.png) [@xedin](https://forums.swift.org/u/xedin)\
**Post date:** [October 22, 2021, 6:18pm UTC](https://forums.swift.org/t/se-0326-multi-statement-closure-parameter-result-type-inference/52964/11 "2021-10-22T18:18:16Z")

</div>

Yes to both of your questions - I have ran public source compatibility suite with this change enabled as well as a large number of other projects and there was only one instance of this ambiguity that I found and one of the two overloads there has been deprecated. If that proves to be a problem bigger problem in the future, we can always mitigate that via a ranking rule, but I think the unified semantics make a lot more sense.

---

<div class="post-metadata">

**Author:** ![mtsrodrigues](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mtsrodrigues/32/34169_2.png) [@mtsrodrigues](https://forums.swift.org/u/mtsrodrigues)\
**Post date:** [October 22, 2021, 7:15pm UTC](https://forums.swift.org/t/se-0326-multi-statement-closure-parameter-result-type-inference/52964/12 "2021-10-22T19:15:41Z")

</div>

That's an amazing improvement. I have one question, thought. Will the following code compile or does it fall into the same case pointed out in Future Directions?

```swift
struct Box {
  let weight: UInt
}

func heavier_than(boxies: [Box], min: UInt) -> [UInt?] {
  let result = boxies.map {
    if $0.weight > min {
       return $0.weight
    }

    return nil
  }

  return result
}

```

---

<div class="post-metadata">

**Author:** ![xedin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/xedin/32/309_2.png) [@xedin](https://forums.swift.org/u/xedin)\
**Post date:** [October 23, 2021, 4:06am UTC](https://forums.swift.org/t/se-0326-multi-statement-closure-parameter-result-type-inference/52964/13 "2021-10-23T04:06:51Z")

</div>

Unfortunately it won't because there is no-join between first and second return statements in the `map` but if you wrote `return boxes.map { ... }` because the result type if inferred from the context. I'm thinking about a possible approach for inference across `return` statements but it's not an easy problem to solve implementation-wise.

---

<div class="post-metadata">

**Author:** ![ExFalsoQuodlibet](https://avatars.discourse-cdn.com/v4/letter/e/bbce88/32.png) [@ExFalsoQuodlibet](https://forums.swift.org/u/ExFalsoQuodlibet)\
**Post date:** [October 23, 2021, 9:38am UTC](https://forums.swift.org/t/se-0326-multi-statement-closure-parameter-result-type-inference/52964/14 "2021-10-23T09:38:41Z")

</div>

I'm super happy and definitely +1 for this, but unfortunately it seems that in this state the proposal would not address what I would consider to be the prime example of the need for multi-statement closure type inference, that is, extracting associated values from enum cases in an ergonomic way.

For example, would the following compile under the current proposal?

```swift
enum Either2<A, B> {
  case a(A)
  case b(B)
}

let eithers: [Either2<Int, String>] = [
  .a(42),
  .b("yello"),
]

let ints = eithers.compactMap {
  guard case .a(let value) = $0 else {
    return nil
  }

  return value
}

// ints should be inferred to be `[Int]`

```

I guess not (or maybe because `compactMap` expects a closure to return some `Optional` it could work, but I'm not sure).

EDIT: I can confirm that it doesn't compile, with `Generic parameter 'ElementOfResult' could not be inferred`. It can be mitigated with the following:

```swift
let x = xs.compactMap {
  guard case .a(let value) = $0 else {
    return Int?.none
  }

  return value
}

```

which is still a major step forward if compared with the current situation 👍

---

<div class="post-metadata">

**Author:** ![ExFalsoQuodlibet](https://avatars.discourse-cdn.com/v4/letter/e/bbce88/32.png) [@ExFalsoQuodlibet](https://forums.swift.org/u/ExFalsoQuodlibet)\
**Post date:** [October 23, 2021, 10:14am UTC](https://forums.swift.org/t/se-0326-multi-statement-closure-parameter-result-type-inference/52964/15 "2021-10-23T10:14:18Z")

</div>

Also, I'm trying to test this with the toolchain linked in the proposal and the flags, but it's not working. I'm not sure if I'm doing it right though.

I downloaded the toolchain and set it in Xcode:

 ![Schermata 2021-10-23 alle 12.09.13](https://global.discourse-cdn.com/swift/original/3X/0/b/0be1f6977f2a98f04abafe689e99314d681b3555.png)

The I created a package and added the flags to the target with the following code (added to the `.target`):

```swift
swiftSettings: [
  .unsafeFlags(
    [
      "-Xfrontend",
      "-experimental-multi-statement-closures"
    ],
    .when(configuration: .debug)
  )]),

```

But I'm getting `<unknown>:0: error: unknown argument: '-experimental-multi-statement-closures'`. Am I doing it wrong?

EDIT: solved by installing the latest snapshot.

---

<div class="post-metadata">

**Author:** ![benrimmington](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/benrimmington/32/695_2.png) [@benrimmington](https://forums.swift.org/u/benrimmington)\
**Post date:** [October 23, 2021, 10:34am UTC](https://forums.swift.org/t/se-0326-multi-statement-closure-parameter-result-type-inference/52964/16 "2021-10-23T10:34:40Z")

</div>

> [@ExFalsoQuodlibet](#):
>
> I'm trying to test this with the toolchain linked in the proposal and the flags, but it's not working.

I think you'll need a more recent [snapshot](https://swift.org/download/#snapshots), so I've updated the proposal.

- The old toolchain was created on **2021-10-05**
- The implementation was merged on **2021-10-09**

Luckily, the downloads should be [faster](https://forums.swift.org/t/faster-swift-downloads/52998) now!

---

<div class="post-metadata">

**Author:** ![ExFalsoQuodlibet](https://avatars.discourse-cdn.com/v4/letter/e/bbce88/32.png) [@ExFalsoQuodlibet](https://forums.swift.org/u/ExFalsoQuodlibet)\
**Post date:** [October 23, 2021, 10:50am UTC](https://forums.swift.org/t/se-0326-multi-statement-closure-parameter-result-type-inference/52964/17 "2021-10-23T10:50:33Z")

</div>

Thanks, with the latest snapshot now it works 👍

---

<div class="post-metadata">

**Author:** ![DevAndArtist](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/devandartist/32/287_2.png) [@DevAndArtist](https://forums.swift.org/u/DevAndArtist)\
**Post date:** [October 23, 2021, 12:17pm UTC](https://forums.swift.org/t/se-0326-multi-statement-closure-parameter-result-type-inference/52964/18 "2021-10-23T12:17:00Z")

</div>

Great proposal. +1

---

<div class="post-metadata">

**Author:** ![ben-cohen](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ben-cohen/32/296_2.png) [@ben-cohen](https://forums.swift.org/u/ben-cohen)\
**Post date:** [November 15, 2021, 4:07pm UTC](https://forums.swift.org/t/se-0326-multi-statement-closure-parameter-result-type-inference/52964/19 "2021-11-15T16:07:44Z")

</div>

## Review Conclusion

The proposal has been [accepted](https://forums.swift.org/t/accepted-se-0326-multi-statement-closure-parameter-result-type-inference/).
