# \[Discussion\] enable \`some\` in closure parameter position

**URL:** <https://forums.swift.org/t/discussion-enable-some-in-closure-parameter-position/53985>\
**Category:** Discussion\
**Created:** [December 11, 2021, 2:03am UTC](https://forums.swift.org/t/discussion-enable-some-in-closure-parameter-position/53985 "2021-12-11T02:03:01Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![ensan-hcl](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ensan-hcl/32/15186_2.png) [@ensan-hcl](https://forums.swift.org/u/ensan-hcl)\
**Post date:** [December 11, 2021, 2:03am UTC](https://forums.swift.org/t/discussion-enable-some-in-closure-parameter-position/53985/1 "2021-12-11T02:03:01Z")

</div>

## Current Situation

A few weeks ago, [SE-0328: Structural opaque result types](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248) was [accepted with modification](https://forums.swift.org/t/accepted-with-modifications-se-0328-structural-opaque-result-type/53789) 🎉

> [@\[Accepted with Modifications\] SE-0328: Structural opaque result type](https://forums.swift.org/t/accepted-with-modifications-se-0328-structural-opaque-result-type/53789/1):
>
> The use of `some` in "consuming" rather than "producing" position when returning function types i.e. `f() -> (some P) -> Void` . Discussion of other uses of the `some` keyword is ongoing, and there was concern about potential conflict with those future uses. Since the use of opaque result types in consuming position is not especially useful (such functions are uncallable in all but a few circumstances) the core team has decided to subset out this use, requiring opaque result types only in the return value of returned function types for now.

As the quote, one of the modifications is relating to `some` in parameter position. In this post, I'd like to share my thought about this point.

In the discussion of [SE-0328](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248), a conflict was found as a problem. Roughly speaking, it is the conflict between structural opaque result types and 'generalized `some` syntax' which has been suggested for years.

```swift
// structural opaque result type
let closure: (some Numeric) -> () = { (value: Double) in print(value) }

// generalized some syntax (generics)
func function(value: some Numeric) { print(value) }

```

The behavior of `closure` can be naturally inferred from the behaviors of other structural opaque result types. `closure` and `function` have the same type at a grance. However, their behaviors are exactly opposite; `function` works as **generic** function.  
The modification is that Swift forbids using, for example, `(some Numeric) -> ()` for a while. But there seems no appropriate solution making both `closure` and `function` possible.

Simpler problem appears in the next example. How can one understand why the first `some Numeric` is generic and the second `some Numeric` is reverse generic? Generalized `some` syntax has confusing problem from the beginning.

```swift
// generalized some syntax (generics) and opaque result type
func function(value: some Numeric) -> some Numeric { value }

```

It is not good to keep the situation as pending. The limitation of `some` usage in parameter position is very artificial considering 'future direction' which most of Swift developers do not know. We should lift it as soon as possible.

## Proposed Solution

Currently, we are trying to introduce three things:

1. Structural opaque result types with **`some`** syntax (SE-0328)
2. Generalized **`some`** syntax (shorthand for generics)
3. Existential **`any`** syntax (explicit marker for exsitentials, [SE-0335](https://forums.swift.org/t/se-0335-introduce-existential-any/53934))

It was ideal that they are compatible with each other. However, 1 and 2 are making collision. There is no way to solve the problem rather than using a different marker. Since it is difficult to consider using `some` for generics and not use for the whole structural opaque result types, generics should use other different marker.

1. Structural opaque result types with **`some`** syntax
2. Generic **`???`** syntax (shorthand for generics)
3. Existential **`any`** syntax (explicit marker for existentials)

This is maybe the simplest and the most consistent solution. There are no artificial limitation and double meaning. With new marker, there is clearer distinction.

```swift
// closure and function behave equally
let closure: (some Numeric) -> () = { (value: Double) in print(value) }
func function(value: Double as some Numeric) { print(value) } // pseudo syntax

// closure and function behave equally
let closure: (??? Numeric) -> () = { print(value) }
func function<T: Numeric>(value: T) { print(value) }
func function(value: ??? Numeric) { print(value) }

// clear distinction between generics and reverse generics
func function(value: ??? Numeric) -> some Numeric { value }

// short hand for generic result types
func function() -> ??? Numeric { 42 }

```

There is room for bikeshedding about `???` marker. The marker should be carefully selected considering relationship among `any`,`some`, and `???`.

## Summary

In summary, I suggested two points in this thread.

- Using `some` for generics causes conflict with structural opaque result types. It is better to use `some` exclusively for reverse generics.
- For generics shorthand, other marker should be come up.

I strongly believe this is the almost only possible solution. I'd like to hear the evaluation of this solution, and what is appropriate for `???` marker. Any thoughts?

## References

> [@SE-0328: Structural opaque result types](https://forums.swift.org/t/se-0328-structural-opaque-result-types/53248/30):
>
> Without strongly taking a side, I’ll note that the Rust folks must have already discussed this when deciding to allow impl Trait in parameter position. [RFC: Finalize syntax and parameter scoping for `impl Trait`, while expanding it to arguments by aturon · Pull Request #1951 · rust-lang/rfcs · GitHub](https://github.com/rust-lang/rfcs/pull/1951)

---

<div class="post-metadata">

**Author:** ![xwu](https://avatars.discourse-cdn.com/v4/letter/x/b487fb/32.png) [@xwu](https://forums.swift.org/u/xwu)\
**Post date:** [December 11, 2021, 3:13am UTC](https://forums.swift.org/t/discussion-enable-some-in-closure-parameter-position/53985/2 "2021-12-11T03:13:15Z")

</div>

I'm not sure what has changed since the prior discussion of SE-0328 that you link to. You've summarized your viewpoints; I will not bother rewriting mine but incorporate them here by referring readers to that link.

Briefly, you and I disagree, as I believe that `some` on the left-hand side of the function arrow _should_ refer to generic parameters and not "reverse" generic parameters, both because the alternative you propose is opposite to how subclassing [edit: and protocol requirement fulfillment] works (inconsistency argument) _and_ dramatically less useful (practicality argument).

The discussion in the Rust community regarding this issue (where the analogous feature is spelled `impl T` rather than `some T`) is illuminating and should be referred to:

> [@jrose](#):
>
> Without strongly taking a side, I’ll note that the Rust folks must have already discussed this when deciding to allow `impl Trait` in parameter position. [RFC: Finalize syntax and parameter scoping for `impl Trait`, while expanding it to arguments by aturon · Pull Request #1951 · rust-lang/rfcs · GitHub](https://github.com/rust-lang/rfcs/pull/1951)

* * *

_If_, on the other hand, feedback from the community is that using `some` in the same way that Rust uses `impl` is too confusing, _then_ I would argue:

- `some` should _not_ be allowed in parameter position at all (the status quo), because a shorthand for reverse generics in parameter position will be of low use (practicality argument) _and_ it would be confusing since others will expect it to be a shorthand for "non-reverse" generics (inconsistency argument); instead, we should build out a longhand version of reverse generics by allowing named parameters in angle brackets on the right side of the function arrow;

- and similarly, _nothing_ should be the shorthand for generics (the status quo) because requiring a _different_ word ("???") would result in treating POP differently from OOP (and protocol constraints from protocol requirement fulfillment)—unnecessarily so—with respect to the function arrow (inconsistency argument).

---

<div class="post-metadata">

**Author:** ![ensan-hcl](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ensan-hcl/32/15186_2.png) [@ensan-hcl](https://forums.swift.org/u/ensan-hcl)\
**Post date:** [December 11, 2021, 9:53am UTC](https://forums.swift.org/t/discussion-enable-some-in-closure-parameter-position/53985/3 "2021-12-11T09:53:04Z")

</div>

> [@xwu](#):
>
> I'm not sure what has changed since the prior discussion of SE-0328 that you link to. You've summarized your viewpoints; I will not bother rewriting mine but incorporate them here by referring readers to that link.

The main reason to create this thread was to have the place for discussion and the problem being more known. SE-0328 thread was not appropriate place to discuss this specific issue.

> [@xwu](#):
>
> The discussion in the Rust community regarding this issue (where the analogous feature is spelled `impl T` rather than `some T` ) is illuminating and should be referred to:

I added it to the post!

---

<div class="post-metadata">

**Author:** ![ensan-hcl](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ensan-hcl/32/15186_2.png) [@ensan-hcl](https://forums.swift.org/u/ensan-hcl)\
**Post date:** [December 12, 2021, 6:02am UTC](https://forums.swift.org/t/discussion-enable-some-in-closure-parameter-position/53985/4 "2021-12-12T06:02:00Z")

</div>

I almost agree with your argument of practicality. It is impossible for me to consider practical usages of such functions. But practicality doesn't support exclusion of a feature. The function in the following code doesn't have practicality, but there is no reason to ban it.

```swift
// there is no way to call the closure
func foo<T>(closure: (T) -> ())

```

If there is no other way rather than using `some` for generics, then we have enough reason to ban `(some P) -> ()`. However, since there are alternative ways to achieve shorthands for generics, banning `(some P) -> ()` doesn't seem to have sufficient reason to introduce such an artificial limitation.

* * *

> [@xwu](#):
>
> because the alternative you propose is opposite to how subclassing [edit: and protocol requirement fulfillment] works (inconsistency argument)

> [@\[Discussion\] Easing the learning curve for introducing generic parameters](https://forums.swift.org/t/discussion-easing-the-learning-curve-for-introducing-generic-parameters/52891/36):
>
> —Not to beat a dead horse, but I wonder if I’m wrong in this: If the pitched syntax generalizing some to generic constraints is adopted, then who chooses the conforming type here: protocol P { } func f(\_: some P) -\> some P { } …exactly parallels who chooses the subtype here: class C { } func f(\_: C) -\> C { }

Are you mentioning this? About it, I think this is just the difference in the way of considering.

`some P` doesn't work how subclassing works even now.

```swift
// subclassing (Dog: Animal)
var da: (Dog) -> Animal = { $0 }
var dd: (Dog) -> Dog = { $0 }
da = dd

// some syntax (T: P)
var ts: (T) -> some P = { $0 }
var tt: (T) -> T = { $0 }
ts = tt // error, because some P is not always T

```

In the code below, the behavioral type of argument and result of `foo` is the same, but in `bar` it's not. Even in generalized `some` syntax there is a behavioral inconsistency.

```swift
// the two 'C' is 'the same type' at least being C
func foo(value: C) -> C { value }
var c: C = C0()
c = foo(value: c)

// generalized `some` syntax
// the two 'some P' is not the same type
func bar(value: some P) -> some P { value }
var p: some P = P0()
p = bar(value: p) // error

```

I'm not sure if it is valid to assume behavioral consistency between the subclassing/`any` types and `some/???` types. In many aspects, `some` syntax behaves differently to how subclassing works. I cannot understand why consistency in subclassing and `some/???` syntax is required.

From the beginning, I think `(C) -> C` is just taking `C` and returning `C`, not caller/callee-decided subclass of `C`. The callee decided to just take `C` and return `C`. Likewise, `(any P) -> (any P)` is just taking `any P` and returning `any P`. The callee can also use `some` to tell 'callee-decided opaque type' and `???` to request 'caller-decided generic type'. Am I missing something?

---

<div class="post-metadata">

**Author:** ![xwu](https://avatars.discourse-cdn.com/v4/letter/x/b487fb/32.png) [@xwu](https://forums.swift.org/u/xwu)\
**Post date:** [December 12, 2021, 6:39am UTC](https://forums.swift.org/t/discussion-enable-some-in-closure-parameter-position/53985/5 "2021-12-12T06:39:05Z")

</div>

> [@ensan-hcl](#):
>
> `some P` doesn't work how subclassing works even now.

Of course `some P` doesn't work like subclassing; they're two distinct features! One feature isn't inconsistent because it's not identical to another feature; rather, a feature is inconsistent if it behaves differently in aspects that are not required to serve its purpose or justification for existing as a distinct feature.

My argument that you quote is that _who chooses_ is dictated by position relative to the _function arrow_ (in other words, parameter versus return type), and it would be inconsistent if that weren't the case for `some P` also, since it is absolutely the case for classes.

On a more basic level, moreover, everyone knows that the caller chooses the parameter _value_ (i.e., argument) and the callee chooses the return _value_. This is never marked with distinct syntax, but based on position relative to the function arrow. In fact, when the callee _can_ modify a parameter value, that's when we add the notation `inout`; in other languages where there is the notion of `out` parameters, those similarly require special notation, not the ordinary `in` parameters.

Likewise, when it comes to inheritance or protocol conformance, Swift allows _contravariant_ parameter types and _covariant_ return types. This is not achieved by distinct spelling, but once again simply by their position relative to the function arrow. Swift does not support _covariant_ parameter types (yet), but in languages such as `Dart` where covariant parameter types are allowed, it's _those_ that are marked differently with a keyword, not the contravariant parameter types.

Stated simply, given any unadorned `(Foo) -> Bar`, I expect that as the caller I get to choose the value and subtype (if any) of `Foo` and the callee gets to choose the value and subtype (if any) of `Bar`. I would be surprised if this did not hold in Swift or any similar language. However, if `some P` is used as a shorthand for "reverse generics," then that would break this basic understanding of how function arrows work. That I regard as inconsistent, because the operator `->` shouldn't change meaning based on what `Foo` and `Bar` are.

---

<div class="post-metadata">

**Author:** ![ensan-hcl](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ensan-hcl/32/15186_2.png) [@ensan-hcl](https://forums.swift.org/u/ensan-hcl)\
**Post date:** [December 13, 2021, 1:24am UTC](https://forums.swift.org/t/discussion-enable-some-in-closure-parameter-position/53985/6 "2021-12-13T01:24:18Z")

</div>

> a feature is inconsistent if it behaves differently in aspects that are not required to serve its purpose or justification for existing as a distinct feature.

If `some` is a shorthand of generics in parameter position, then the decider inconsitency can be a problem. But I'm proposing `some` as the shorthand of reverse generics. Being chosen by the callee is the fundamental and necessary part of 'reverse generics', isn't it? It doesn't unnecessarily behave differently.

> Stated simply, given any unadorned `(Foo) -> Bar`, I expect that as the caller I get to choose the value and subtype (if any) of `Foo` and the callee gets to choose the value and subtype (if any) of `Bar`.

I'm not sure what will the `some/???` syntax break practically after all. `some/???` in parameter position is still only in consuming position, and `some/???` in result position is only in producing position too. The meaning of function arrow does not change. I think the source of your confusion is mixing up the idea of substituting a type parameter with concrete type and choosing underlying type of a supertype. They are two distinct concept. Basically, type parameters are decided at compile time, while underlying types can be even random at runtime. I admit `some` as generics can be explained in your way, but it's not an essential part.

* * *

FWIW, using `some` only for reverse generics, `some P` behaves as if it is the subtype of `any P`. This in itself does not support either argument, but I found it interesting.

---

<div class="post-metadata">

**Author:** ![xwu](https://avatars.discourse-cdn.com/v4/letter/x/b487fb/32.png) [@xwu](https://forums.swift.org/u/xwu)\
**Post date:** [December 13, 2021, 1:31pm UTC](https://forums.swift.org/t/discussion-enable-some-in-closure-parameter-position/53985/7 "2021-12-13T13:31:02Z")

</div>

> [@ensan-hcl](#):
>
> If `some` is a shorthand of generics in parameter position, then the decider inconsitency can be a problem. But I'm proposing `some` as the shorthand of reverse generics. Being chosen by the callee is the fundamental and necessary part of 'reverse generics', isn't it? It doesn't unnecessarily behave differently.

To be clear, there is no actual feature named “reverse generics.” The feature spelled `some P` is an _opaque type_, and the question to be answered is: opaque to whom?

_I_ was one of the first folks here who pointed out that, when used in return position, an opaque type is like a generic constraint but “reverse” in terms of who chooses the underlying type (caller versus callee). The term “reverse generics” was meant as a way of describing what an opaque type is _when used in return position_—that is, _relative to the function arrow_.

In a scenario such as `let x: some Numeric = 42 as Int` (when supported), it’s still an opaque type that’s involved but there is no sense in which there is anything “reverse” about it.

> [@ensan-hcl](#):
>
> I think the source of your confusion is mixing up the idea of substituting a type parameter with concrete type and choosing underlying type of a supertype. They are two distinct concept. Basically, type parameters are decided at compile time, while underlying types can be even random at runtime.

I’m no more confused about the distinction between type parameters and subclassing any more than I am about the distinction between types and values. What I’m saying is that the topic here is the question of _who chooses_ relative to a function arrow, and in all of these scenarios the caller chooses on the left-hand side and the callee chooses on the right-hand side.

---

<div class="post-metadata">

**Author:** ![gwendal.roue](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/gwendal.roue/32/13992_2.png) [@gwendal.roue](https://forums.swift.org/u/gwendal.roue)\
**Post date:** [December 13, 2021, 1:59pm UTC](https://forums.swift.org/t/discussion-enable-some-in-closure-parameter-position/53985/8 "2021-12-13T13:59:09Z")

</div>

I don't know if this is the correct thread to post this, but the [Motivation](https://github.com/rust-lang/rfcs/blob/master/text/1951-expand-impl-trait.md#motivation) section of the Rust RFC that accepts `impl Trait` (more or less our `some P`) as an argument (after it was already used as a return type), is really well written. The [critique rebuttals](https://github.com/rust-lang/rfcs/blob/master/text/1951-expand-impl-trait.md#critique-from-the-lang-team) are quite interesting as well.

I also learned today, in [The Evolutions of Lambdas in C++14, C++17 and C++20](https://www.fluentcpp.com/2021/12/13/the-evolutions-of-lambdas-in-c14-c17-and-c20/), that C++ accepts `auto` for both caller-supplied types and callee-supplied types.

Reasoning by analogy is full of traps, so I wouldn't personally rush to conclusion. Yet, right in front of my eyes, I see two major languages that tend to agree that _programmers have a very deep intuition around the difference between arguments and return values, and "who" provides which (amongst caller and callee)_ (quoted from the Rust RFC).
