# \[Discussion\] Eliding \`some\` in Swift 6

**URL:** <https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918>\
**Category:** Discussion\
**Tags:** generics, opaque-types\
**Created:** [June 8, 2022, 4:11pm UTC](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918 "2022-06-08T16:11:16Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![hborla](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hborla/32/27563_2.png) [@hborla](https://forums.swift.org/u/hborla)\
**Post date:** [June 8, 2022, 4:11pm UTC](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918/1 "2022-06-08T16:11:17Z")

</div>

Swift 5.7 includes a suite of new language features that together enhance the expressivity and usability of `any` and `some` types, making abstract code more approachable and easier to internalize.

In addition to making a lot of common generic code patterns easier to write by eliding an explicit generic signature completely, Swift 5.7 makes it very easy to switch between `any` types and `some` types. Currently, the default for writing a plain protocol name in type position is `any`, but many of these implicit `any` uses could be replaced with `some`, giving them more type information while still behaving correctly.

The `any` keyword will be required in Swift 6, which opens an opportunity to change the default when writing a plain protocol name to `some` instead of `any`. This post explores the motivation and implications for making such a change.

**Feedback from your hands-on experience internalizing and applying the new generics features in Swift 5.7 is welcome and crucial for informing this exploration!** In particular, I'm interested to know things such as:

- Whether you find the `some` keyword in opaque result types more clarifying now that (hopefully) programmers are starting to gain a better understanding of opaque result types. Pre-5.7, I'd received a lot of feedback that people don't know what `some` really means and they just stick it into their SwiftUI views to satisfy the compiler.
- What kinds of code are you able to modernize in Swift 5.7?
- How often do you use `any` versus `some`?
- Where are you able to change `any` to `some` (or insert `some` in front of a bare protocol name in existing code)?

## Use cases for `some` and `any`

The `some` and `any` keywords have different capabilities, and will be useful in different contexts in a project.

`some` guarantees a fixed underlying type, which preserves static type relationships to that underlying type, giving you full access to the protocol requirements and extension methods that use `Self` and associated types. These are the semantics that programmers typically expect when working with protocols, and have many use cases in abstract code, including (but not limited to):

- Local `let`-constants, including `for-in` variables, e.g. when iterating over a heterogeneous collection. Because the variable cannot be re-assigned to have a different underlying type, there’s little reason to use `any` instead of `some`.
- Local `var`s whose underlying type does not change (only the value changes).
- Non-`inout` function and method parameters, and `inout` parameters whose underlying type does not change (only the value changes).
- Single-statement computed property or method result types, and result builder bodies that preserve type information such as `@ViewBuilder` and similar DSLs.

`any` provides a common supertype for all concrete types that meet the given requirements. Using `any` is a form of type erasure that allows you to store any arbitrary subtype dynamically by using a boxed representation in memory. Type erasure has a number of use cases where you need the ability to change or mix different underlying types, such as:

- Local `let` -constants that have different initial types across different control-flow paths, and `var`s whose underlying type changes.
- Heterogeneous collections, e.g. `[any DataSourceObserver]`
- Optionals that are assigned an underlying type later, e.g. `var delegate: (any UITableViewDelegate)? = nil`
- Stored properties of types that use a protocol abstraction, but the enclosing type is not parameterized. The delegate pattern above is a common example of abstraction as an implementation detail of a concrete type.

For `any` types, where the underlying type can vary, the protocol requirements and methods involving `Self` and associated types are not available from the box itself; if the underlying type can vary, so can the protocol requirements that depend on that type, so there is no way to know what the signature of a requirement using `Self` or associated types in contravariant or invariant position is. For this reason, programmers are encouraged to write `some` by default, and change `some` to `any` when the storage flexibility is needed. This workflow is similar to writing `let` constants by default until mutation is needed.

## Should `some` be the default in Swift 6?

Encouraging writing `some` by default begs the question of whether `some` should be the default for a plain protocol name in the language, just like how `let` is the default whenever the variable introducer is omitted, such as in parameters and `for-in` loops. In Swift 6, a plain protocol name `P` could still be valid code, but it would mean `some P` instead of `any P`.

Writing `any` explicitly is important for understanding the type-erasing semantics and the limitations of using this type, including the ability to change the underlying type, the inability to access `Self` and associated type requirements, etc. These limitations don’t exist for `some` types, which provide full access to the protocol requirements and extension methods. In fact, `some` already is the default for protocol extensions, e.g.

```swift
// Extends all concrete types conforming to 'Collection'.
// The 'Self' type parameter serves as a placeholder for the
// concrete type conforming to 'Collection'.
extension Collection { ... }

```

In a protocol extension, you write generic code that operates on a `Self` type parameter that conforms to the protocol. In this case, the bare protocol name is already sugar for declaring a type parameter conforming to the protocol. Protocol extensions have proven to be a very natural way to write generic code. The same principle could be applied to plain protocol names in Swift 6 to enable programmers to write generic functions naturally without having to fully internalize explicit generic signatures with `where` clauses.

In many use cases for `some`, it’s already evident in the code that the underlying type will never change. For example, a `let` constant or a non-`inout` parameter already indicates that the underlying type cannot change. Similarly, opaque result types in single-return methods and result builders clearly have one underlying return type.

In Swift 5.7, you can write a `zip` function using the `some` keyword for both arguments and the result type:

```swift
func zip<E1, E2>(_: some Sequence<E1>, _: some Sequence<E2>) -> some Sequence<(E1, E2)>

```

Eliding the `some` keyword, this declaration would read:

```swift
func zip<E1, E2>(_: Sequence<E1>, _: Sequence<E2>) -> Sequence<(E1, E2)>

```

In addition to eliding the `some` keyword in type annotations, the language could default to `some` in more places, such as local variable assignments to an `any` type without a type annotation, where it’s possible to open the existential value:

```swift
let observers: [any DataSourceObserver]

for observer in observers {
  // The default for `observer` could be (some) `DataSourceObserver`,
  // which means the scope of this for-loop would be a context
  // where you have access to Self and associated types
}

```

## Observations and open questions

Brainstorming this idea has surfaced a number of observations that are worth discussing.

First, there are a few cases where the `some` keyword could be considered clarifying. For example, the `some` in `[some Comparable]` communicates that the array is homogeneous. Similarly, in `var value: some P = ConcreteP()`, the `some` keyword conveys that the underlying type cannot change.

Composing type parameters with `Optional` is tricky to work with, because passing `nil` doesn’t provide a generic argument type, so replacing `any` with `some` for optional function parameters might not be as straightforward as changing the keyword. One of the main use cases of optional `any` parameters could be changed to use [SE-0347](https://github.com/apple/swift-evolution/blob/main/proposals/0347-type-inference-from-default-exprs.md) instead, and provide a concrete default argument instead of `nil`.

Eliding `some` is not possible when only using a superclass constraint. There isn’t much benefit to writing `some ClassType` over using the class type directly, so this is probably okay.

An obvious downside of changing the semantics of existing syntax in Swift 6 is that numerous resources, such as Swift Forum questions and blog posts, have been created over the years using the existing syntax. This content will become outdated with Swift 6, where previously-existential code would have different semantics. However, programmers will already need to evolve their understanding of `any` types with [SE-0309](https://github.com/apple/swift-evolution/blob/main/proposals/0309-unlock-existential-types-for-all-protocols.md) in Swift 5.7, which introduces the need to reason about uses of associated types in protocol requirements when working with `any` types. So, content that features existential types will already need to be updated to apply to Swift 6, and there’s a fair amount of existing existential code that could flip to using generics and still behave correctly, as mentioned earlier.

Finally, because a lot of existing code can switch from `any` to `some` and still behave correctly, eliding `some` may ease the transition to Swift 6 by requiring less code churn, and even improving the semantics of some existing Swift code.

## Alternatives considered

In this post, I’ve outlined the common use cases for `some` and `any`. A common suggestion is to formalize the heuristics for when `some` is most useful versus when `any` is most useful, and use those heuristics as rules for defaulting to `some` in certain cases and defaulting to `any` in others. However, this model would re-introduce the conflation between the semantics of existential types and opaque types, and it would lead to a frustrating developer experience in the face of refactoring and code evolution. Innocuous changes, such as factoring a local variable into a stored property, would end up changing the _type_ of values unexpectedly and cause programmers to re-structure code that is seemingly unrelated to the refactoring task at hand, such as moving code that operated on that local variable into a separate function accepting `some`.

---

<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:** [June 8, 2022, 4:29pm UTC](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918/2 "2022-06-08T16:29:47Z")

</div>

My gut reaction is that it feels somewhat... aggressive to change the behavior of bare `P` in the _same_ release where we're requiring the use of `any`. I think I'd prefer if we give some time for Swift 6 to 'settle', and then reintroduce the 'bare `P`' syntax in a future release (and since it's purely additive syntax in Swift 6.x, it could even be a minor release).

More concretely, using an example raised in your post:

> Similarly, in `var value: some P = ConcreteP()`, the some keyword conveys that the underlying type cannot change.

Long term (say, Swift 7 and beyond), I'm not sure it makes a ton of sense to _require_ `some P` here instead of just `P`, even if users could more clearly document their intent by writing `some`. But if Swift 6.0 allows `P` to mean `some P` in this position, we'd be silently changing behavior from Swift 5.x where `value` had type `any P`, which I think is also untenable.

So that would leave the transition in a middle ground where we'd change the meaning of bare `P` in some circumstances but emit an error in others, only to _eventually_ enable it everywhere. That seems... overly messy to me compared to first requiring the removal of _all_ 'bare `P`' usages to transition to Swift 6, followed by the incremental introduction of the bare-`P`-as-`some`-`P` syntax.

---

<div class="post-metadata">

**Author:** ![Paul\_Cantrell](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/paul_cantrell/32/16764_2.png) [@Paul\_Cantrell](https://forums.swift.org/u/Paul_Cantrell)\
**Post date:** [June 8, 2022, 4:31pm UTC](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918/3 "2022-06-08T16:31:44Z")

</div>

My initial reaction to this is that the words “some” and “any” provide crucial mental scaffolding for these confusing questions, and it's best to keep them in the mix **whenever explicitly referring to a type by name**.

We shouldn’t ever think of “just `P`” being a type that a variable or function can have; it’s always either `some P` or `any P`. Both come with limitations that are surprising if we don't have the idea of “some” or “any” firmly fixed in mind when reasoning about the type.

One of the best things about where we’re currently heading with Swift 6 is that this distinction is clear, and we have a clear language for talking about it. And that clear language shows up _in the syntax_ in a way that supports casual heuristics as a stepping stone to deeper understanding, in keeping with Swift’s general design principle of progressive disclosure.

In situations where there is no explicit type name, defaulting to `some` seems fine. So, for example, this makes perfect sense — is positively beneficial, even, since it’s not obvious that `some` is both allowed and better in this situation:

```swift
let observers: [any DataSourceObserver]
for observer in observers { // `observer` is `some DataSourceObserver`
   …
}

```

This, however, strikes me as pretty dicey:

```swift
func zip<E1, E2>(_: Sequence<E1>, _: Sequence<E2>) -> Sequence<(E1, E2)>

```

* * *

Concerns about migration path and accidental “any becomes some” effects of grabbing pre-6 example code are also compelling. At a minimum, a [phased rollout](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918/2) seems wise.

However, even imagining this as a green field problem, I tend to prefer explicit some vs. any. If that distinction exists _at all_ in the language, it should be very clear.

I may well revise my opinion about all this after diving in with Swift 5.7.

* * *

As an aside, the “Use cases for `some` and `any`” section is one of the best short descriptions I’ve read of what this distinction means in practice for developers. Distribute that text far and wide!

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [June 8, 2022, 4:43pm UTC](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918/4 "2022-06-08T16:43:42Z")

</div>

We don't technically have a schedule for Swift 6 yet, but I share the concern that this seems like a very fast turnaround for re-using bare protocol names with different semantics. Adding `any` isn't something that's had much time to gain much traction in the community and the collective Swift codebase. I think it would be wiser to give people more time to wrap their heads around the post-5.7 world of generics.

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [June 8, 2022, 4:50pm UTC](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918/5 "2022-06-08T16:50:54Z")

</div>

One potential midpoint we could take is to make `some` the default in places where `some` or `any` doesn't really affect the domain of a function, particularly for non-`inout` function arguments. With the recent additions to generalize existentials and allow for implicit opening, `func foo(_: some P)` and `func foo(_: any P)` both accept the same sets of parameters and have the same sets of capabilities operating on their arguments, but `func foo(_: some P)` is slightly more efficient as public ABI because it can accept a conforming value as-is without boxing it, and also more flexible by default inside the body of `foo`, since you can use all of `P`'s methods on it without an opening step. It would make sense to favor the more efficient, more expressive interpretation of `func foo(_: P)` to mean `func foo(_: some P)`, independent of what we choose to do in places where there's an effective semantic difference.

---

<div class="post-metadata">

**Author:** ![hborla](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hborla/32/27563_2.png) [@hborla](https://forums.swift.org/u/hborla)\
**Post date:** [June 8, 2022, 4:58pm UTC](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918/6 "2022-06-08T16:58:06Z")

</div>

> [@Joe\_Groff](#):
>
> `func foo(_: some P)` and `func foo(_: any P)` both accept the same sets of parameters and have the same sets of capabilities operating on their arguments

I don't think this is true - the function accepting `any P` does not have the ability to access `Self` and associated type requirements in invariant or covariant position in protocol methods. If you try in Swift 5.7, you'll get an error and a fix-it to change `any` to `some`.

I also think taking this approach will lead to a confusing model because programmers will need to deeply understand where they can omit `some` and where they cannot. For example, you'd be able to write a parameter of type `P`, but not of type `[P]`.

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [June 8, 2022, 5:00pm UTC](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918/7 "2022-06-08T17:00:28Z")

</div>

> [@hborla](#):
>
> I don't think this is true - the function accepting `any P` does not have the ability to access `Self` and associated type requirements in invariant or covariant position in protocol methods. If you try in Swift 5.7, you'll get an error and a fix-it to change `any` to `some` .

Not directly on the argument, but you can still open it locally without changing the external interface:

```swift
func foo(_ x: any P) {
  func foo2(_ x: some P) { ... }
  foo2(x)
}

```

Suggesting changing the outer argument type from `any` to `some` might not be possible if the argument is existing public API, since that's an ABI-breaking change. I think it'd be great to encourage the "easy way" of writing a function that takes all values conforming to a protocol to be the most efficient one by default. I see what you're saying about it being potentially confusing exactly when you can elide `some`/`any`. On the other hand, the compiler can help here too, and it might be easier to explain why you need `some` or `any` in contexts where the choice has obvious unsubtle effects on what the function can do.

---

<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:** [June 8, 2022, 5:04pm UTC](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918/8 "2022-06-08T17:04:07Z")

</div>

That’s kind of the “middle ground” I was getting at above, and I really don’t think it’s a very tractable transition process. Bare `P` would be accessible in only a limited set of places, and I agree with @hborla —I think it would be difficult to explain why.

Also, even for function parameters I don’t think the ‘direct’ transition is quiiiite as transparent as we’d want. E.g., the following would start failing on the `let f = ...` line, right? I think it's much better if this becomes a compilation error on the line that defines `takesBareP`.

```swift
func takesBareP(_: P) {}

let f = takesBareP

```

---

<div class="post-metadata">

**Author:** ![filip-sakel](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/filip-sakel/32/8697_2.png) [@filip-sakel](https://forums.swift.org/u/filip-sakel)\
**Post date:** [June 8, 2022, 7:19pm UTC](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918/9 "2022-06-08T19:19:33Z")

</div>

There are already a lot of rules around opening existentials in SE-0352, which may be surprising in some cases. For example, printing the type of an implicitly opened parameter can actually output the opaque type, which may surprise users that aren't really up-to-date with the latest evolution proposals. I think this was acceptable in the case of SE-0352 as a compromise; here, however, we could leave things as they are, such that there's a clear distinction between generics and existentials.

I agree with @Jumhyn that at least for now, `some` shouldn't be elided, but I think it would make for a good quality-of-life improvement in the future.

> [@Paul\_Cantrell](#):
>
> One of the best things about where we’re currently heading with Swift 6 is that this distinction is clear, and we have a clear language for talking about it. And that clear language shows up _in the syntax_ in a way that supports casual heuristics as a stepping stone to deeper understanding, in keeping with Swift’s general design principle of progressive disclosure.

I don't think keeping `some` everywhere will help progressive disclosure in the long run. In function parameters, for example, the bare syntax implying an existential, made sense to a lot of users (before running into an edge case). Similarly, since `some` will become the default, I think it will be intuitive to give it the bare-protocol syntax since this syntax doesn't have an intrinsic characteristic hinting at either generics or existentials. Then again, progressive disclosure may not be desired here, since the type of abstraction is arguable an important detail, and thus justifies a steeper learning curve.

---

<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:** [June 8, 2022, 8:21pm UTC](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918/10 "2022-06-08T20:21:10Z")

</div>

> [@filip-sakel](#):
>
> I agree with @Jumhyn that at least for now, `some` shouldn't be elided, but I think it would make for a good quality-of-life improvement in the future.

I agree with @Jumhyn, @John_McCall and @filip-sakel that the overall direction is very nice but the timeline seems to be too compressed.

I think having no major version between prohibiting bare protocol syntax and adopting it for another meaning effectively eliminates any transition at all: the net effect would then be a silent change in the meaning of existing code which, as I’ve argued in other scenarios, is one of the least desirable sorts of source-breaking change.

The community has really mobilized with some wonderful tutorials explaining the upcoming accepted changes. It seems that it would add to confusion rather than reduce it if users were to find that code they’re learning is no longer going to work somehow still compiles, contrary to all of these wonderful tutorials, and then only to discover down the line that it works differently.

---

<div class="post-metadata">

**Author:** ![Paul\_Cantrell](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/paul_cantrell/32/16764_2.png) [@Paul\_Cantrell](https://forums.swift.org/u/Paul_Cantrell)\
**Post date:** [June 8, 2022, 8:35pm UTC](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918/11 "2022-06-08T20:35:34Z")

</div>

> [@filip-sakel](#):
>
> In function parameters, for example, the bare syntax implying an existential, made sense to a lot of users (before running into an edge case). Similarly, since `some` will become the default, I think it will be intuitive to give it the bare-protocol syntax

I suspect that “any by default” may make sense to people because in the vast majority of statically typed languages that people are coming from — Objective-C, Java, Typescript, C#, Go, Dart, Scala, even C++ — the bare name of an abstract type indicates an existential of some kind.

Implementation details are all over the map, and not all of them refer to a value-side box as in Swift…but in all of them, the user-visible presentation of a variable `x` of type `InterfaceOrTraitOrProtocolName` behaves like Swift’s `any`: runtime type of a mutable variable can change, same-associated-type knowledge requires a generic, collections can be heterogenous, methods are dynamically dispatched, etc.

In fact, AFAIK, nothing like Swift’s opaque return types even _exists_ at the user-visible surface any of these languages. They do exist under the hood as a compiler optimization in many of these, but for the language user's point of view, everything looks like an existential type. Only Rust has a surfaced distinction (`impl` / `dyn`) similar to Swift’s (`some` / `any`).

Again, I might change my tune after spending some quality time with Swift 5.7, but it does seem to me that “same by default” runs upstream against a whole lot of precedent.

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [June 8, 2022, 10:58pm UTC](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918/12 "2022-06-08T22:58:53Z")

</div>

> [@hborla](#):
>
> In Swift 5.7, you can write a `zip` function using the `some` keyword for both arguments and the result type:
> 
> ```swift
> func zip<E1, E2>(_: some Sequence<E1>, _: some Sequence<E2>) -> some Sequence<(E1, E2)>
> 
> ```
> 
> Eliding the `some` keyword, this declaration would read:
> 
> ```swift
> func zip<E1, E2>(_: Sequence<E1>, _: Sequence<E2>) -> Sequence<(E1, E2)>
> 
> ```

~~IMHO this is quite logical and worth doing.~~  
_Edit: I take this back, [the following message](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918/70) convinced me that keeping explicit "some" is a good idea._

I'd even drop the first angle brackets... they could be derived:

```swift
func zip<E1, E2>(_: Sequence<E1>, _: Sequence<E2>) -> Sequence<(E1, E2)>
↔
func zip(_: Sequence<E1>, _: Sequence<E2>) -> Sequence<(E1, E2)>

```

---

<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:** [June 8, 2022, 11:09pm UTC](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918/13 "2022-06-08T23:09:57Z")

</div>

I'd like to reiterate the concern that making bare `P` mean `some P` in the same version that removes the implicit `any P` seems aggressively fast. This will be an additive change, and can be added to any later 6.x version. I don't think we should do this for 6.0.

---

<div class="post-metadata">

**Author:** ![toph42](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/toph42/32/7807_2.png) [@toph42](https://forums.swift.org/u/toph42)\
**Post date:** [June 8, 2022, 11:14pm UTC](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918/14 "2022-06-08T23:14:06Z")

</div>

I agree that there should be a version step between bare `P` becoming `any P` and `some P` becoming bare `P`. A simultaneous change is no transition at all.

---

<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:** [June 9, 2022, 12:33am UTC](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918/15 "2022-06-09T00:33:38Z")

</div>

I think it's important to distinguish "is this the right thing to do" from "when to time the change. I think this thread is probably jumping prematurely to the "when", whereas it is probably better to start with the "is it right". Bear in mind, this is a discussion thread, not even a pitch. I think the first question to answer is whether the default actually should be flipped. Then after that, it's worth looking at what the migration path might be.

That said, let's talk briefly about the timing part, while _for now_ assuming that it _is_ the right thing to do.

> [@toph42](#):
>
> I agree that there should be a version step between bare `P` becoming `any P` and `some P` becoming bare `P` . A simultaneous change is no transition at all.

I think, when flipped around, this comment perfectly describes why it is potentially _important_ to bundle these two change together, and that separating them will lead to inconvenience and confusion for developers.

Consider that, as Joe points out above, now we have opening a function that takes an existential argument is _usually_ indistinguishable to the caller from a function that takes a generic argument.\* And updating a function that takes an existential argument to one that takes a generic argument is usually not something that requires any changes to the function implementation.

What this means is that developers may find that many functions need no change when flipping the default for bare protocols. They compile today as `any` as the default, and they will compile tomorrow with `some` as the default.

If we separate mandating `any` from flipping the default, this means the migration will be in two stages:

- First, developers need to go through `any` and `some` into their code when they migrate to Swift 6
- Then, in a later release, they get to take the `some` out again.

For the first phase, the developer will need to decide what to do... should it be `any` or `some`? `any` might seem like the safe choice, but chances are `some` would be the better one. (Bear in mind, because we have not had opening all along, there are many functions that are out there written to take existentials _because_ they were being passed existentials... something that's no longer necessary) If they choose to go the `some` route, they will be littering their code with a keyword only to allow them to taken it out again later.

By contrast, by combining the two moves together, a codebase that has a bunch of functions that take existentials, and that hasn't been touched since 5.7 meant it could switch those to generic functions, can just take the flip without needing to two-step insert `some` then be able to take it out again. That's really not a great experience for users.

Now this doesn't account for other cases, like functions that take an optional existential, which cannot just switch to `some` because opening won't work with optionals. I think some discussion should be had around how to tackle this kind of migration. Even without flipping the default, I think we'll want some tooling to help people analyze their codebases to help make the right choice about whether to add `some` or `any`, based on looking at callers. And there is a question of whether packages with public interfaces should have a different migration strategy to source code for closed systems where, even though you have frameworks with public functions

I'm also not addressing storage here, just arguments. But I think in a way that's an easy migration too: `some` is probably going to almost _never_ be the right choice for a variable, except when it's initialized with type inference, so we proably will end up with a migration assistant for that which would just add the `any` in. The best practice here would be to encourage people to do it ahead of migrating to Swift 6, since the `any` keyword will have existed for at least 1.5 years prior to that happening.

---

<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:** [June 9, 2022, 2:11am UTC](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918/16 "2022-06-09T02:11:17Z")

</div>

> [@ben-cohen](#):
>
> I think the first question to answer is whether the default actually should be flipped.

I agree we shouldn't get _too_ involved in debating "when should we do this?" when "should we do this at all?" is an open question, but it's possible IMO that each question would inform the other—e.g., it might be that flipping the default would be highly desirable for the sake of easing the transition, but _reintroducing_ bare `P` after it has been fully purged from most active codebases wouldn't pull its own weight.

So, further on timing... 🙂

I think this in particular:

> [@ben-cohen](#):
>
> What this means is that developers may find that many functions need no change when flipping the default for bare protocols. They compile today as `any` as the default, and they will compile tomorrow with `some` as the default.

is quite a strong case for investigating switching the default for bare `P` in Swift 6. If it's really the case that we could dramatically reduce the burden of the 'bare `P`' removal transition, that would be great.

That said,

> [@ben-cohen](#):
>
> If we separate mandating `any` from flipping the default, this means the migration will be in two stages:
> 
> - First, developers need to go through `any` and `some` into their code when they migrate to Swift 6
> - Then, in a later release, they get to take the `some` out again.

it doesn't make a whole lot of sense to me to frame this as a "two stage" migration. We didn't frame it as a single-stage 'migration' when we introduced the `if let x` shorthand—it's just a new convenience that _new_ code can make use of going forward.

The value in changing the meaning of bare `P` in Swift 6 isn't that it _saves_ us a step, it's what you note above: that it (potentially) reduces the _impact_ of the `P` to `any P` migration by a pretty significant margin. To properly evaluate the difference between the one-step and two-step approaches, I think we'll want to at least explore:

- For what proportion of bare `P` uses would flipping the default completely obviate the need for the user to do _any_ migration?
- In cases where flipping the default doesn't 'just work', how much more difficult will the failures be to explain and/or fix?
- Will we be able to confidently catch and diagnose during migration any situations where semantics might silently change, or alternatively, will such instances be so exceedingly unlikely that we need not worry about them?

This last item is particularly important—I agree with @xwu that a silent behavior change is more insidious than a new compiler error, so I think our confidence level should be quite high that such instances will (almost) never happen in real-world code.

---

<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:** [June 9, 2022, 2:14am UTC](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918/17 "2022-06-09T02:14:49Z")

</div>

> [@Jumhyn](#):
>
> We didn't frame it as a single-stage 'migration' when we introduced the `if let x` shorthand—it's just a new convenience that _new_ code can make use of going forward.

I think that's a little different though. By mandating `any`, we are _requiring_ that people uglify their code (whether they stick with `any` or switch to `some`), and then if we _later_ flip the default, they will only then be able to beautify it again.

Now sure, the beautification is optional, just like with `if let`. But what's different is it's re-beautification because today, it looks better than it temporarily will have to.

---

<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:** [June 9, 2022, 3:09am UTC](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918/18 "2022-06-09T03:09:14Z")

</div>

> [@ben-cohen](#):
>
> I think that's a little different though. By mandating `any` , we are _requiring_ that people uglify their code (whether they stick with `any` or switch to `some` ), and then if we _later_ flip the default, they will only then be able to beautify it again.

Yeah, I take your point. I just think talking about it as a two-step migration misstates how it will actually be experienced by most users. It won’t be a “agh, now I have to change all my protocol types _again_?” when (if) the bare `P` syntax is brought back, it will be “ah, neat, now I can stop writing `some` all the time.” I think the stronger point is that flipping the default later potentially makes the migration (or, the first step) _much_ more painful than necessary.

I also suppose I feel like the `some P` syntax is sufficiently lightweight and beautiful in its own right that I don’t think it’s all that bad if there’s a large number of lingering `some`s in a codebase that _could_ be removed, eventually.

---

<div class="post-metadata">

**Author:** ![QuinceyMorris](https://avatars.discourse-cdn.com/v4/letter/q/d26b3c/32.png) [@QuinceyMorris](https://forums.swift.org/u/QuinceyMorris)\
**Post date:** [June 9, 2022, 5:13am UTC](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918/19 "2022-06-09T05:13:48Z")

</div>

> [@Jumhyn](#):
>
> > [@ben-cohen](#):
> >
> > I think that's a little different though. By mandating `any` , we are _requiring_ that people uglify their code (whether they stick with `any` or switch to `some` ), and then if we _later_ flip the default, they will only then be able to beautify it again.
> 
> Yeah, I take your point. I just think talking about it as a two-step migration misstates how it will actually be experienced by most users. It won’t be a “agh, now I have to change all my protocol types _again_ ?” when (if) the bare `P` syntax is brought back, it will be “ah, neat, now I can stop writing `some` all the time.”

I don't disagree with you. I also don't disagree with @ben-cohen's argument — in isolation.

The problem here is that members of the compiler team are very close the changes and the semantics of the new `some`/`any` syntax. They know what it is, they're comfortable with it.

I predict that other developers further from the center of the universe (especially those who don't get tutorialized by visiting the Swift forums), when faced with the upcoming `any` changes, will have to spend some time grasping what the new `some P` and `any P` mean _at all_, let alone fathom an invisible change to bare `P`.

I predict that even developers who would accept the advice that a `some`-less `P` is what they should in general be using, will use it without really knowing why it's what they should be using — at least at first.

It seems to me there's an argument that requiring `some`, initially, will be a useful discipline for understanding, rather than a useless exercise in syntax.

> [@Jumhyn](#):
>
> I don’t think it’s all that bad if there’s a large number of lingering `some` s in a codebase that _could_ be removed

I don't disagree with that, either. Also, we know that there's a large cadre of "completionist" developers out there — developers who, for example, choose to prefix their instance property names with `self.` although it isn't syntactically necessary. Not everyone is going to choose to eliminate unnecessary `some`s.

---

<div class="post-metadata">

**Author:** ![Moximillian](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/moximillian/32/3055_2.png) [@Moximillian](https://forums.swift.org/u/Moximillian)\
**Post date:** [June 9, 2022, 5:20am UTC](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918/20 "2022-06-09T05:20:25Z")

</div>

I think eliding some would be a step in wrong direction. We just have swift proposals and wwdc 2022 videos explaing that plain protocol (as constraint) and protocol as type are two different things and the any/some make that distinction more explicit and understandable.

After all that work and effort to make swift more clear and understandable, we go backwards and add more confusion again?

There’s been a few proposals around (like the if let) which optionally remove syntax just for the sake of removing syntax. I find this worrying. Those kind of things take away possibilities to make swift a easy to understand language.

We don’t want a language where developers make the right choice by accident (i.e. elided some) and then don’t understand how to do heterogenous version if they need it. We want people to make conscious choice between some/any and understand the difference between them.

[Next page](https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918.md?page=2)
