Hi everyone. The review of SE-0352: Implicitly Opened Existentials ran from April 5…April 18, 2022. The core team has decided to return the proposal for revision. Although discussion was almost unanimously positive, and largely consisted of clarifying questions, there is one important design decision to clarify regarding the behavior of covariantly-erased return types in the face of other language evolution. Given the following example:
protocol P {
associatedtype A: Collection<Int>
}
func foo<T: P>(x: T) -> T.A { ... }
func bar(_: some Collection) { print("comme ci") }
func bar(_: some Collection<Int>) { print("comme ça") }
func callFooWithAnyP(x: any P) {
let y = foo(x)
bar(y)
}
then under the language today, the best type-erased result type from the call to foo
we can come up with today would be any Collection
, which would then be inferred for the type of y
. However, if the language gains more expressive existentials in the future, such as same-type constrained existential types, then we could conceivably infer a narrower upper bound type for y
, such as any Collection<Int>
, which can affect overload resolution in source-breaking ways. In the above example, improving the type erasure behavior would cause bar(y)
to select the second overload of bar
instead of the first.
We want to be able to continue to improve the expressivity of existentials without breaking existing code, but we want the return values of functions called with opened existentials to be as useful as possible. The core team would like to see the proposal undergo another round of review to explore this design space. This isn't technically a new problem, since as soon as SE-0309 allowed all protocols to be used in existential types, it was possible to create similar situations using return types involving associated types, but SE-0352 makes the problem more pervasive, and we want to make sure we have a satisfying consistent answer to this problem going forward. The proposal for same-type constrained existential types is also ready for review concurrently, providing a timely concrete example of expanding the expressivity of existential types, and a chance to consider its interaction with covariant erasure when opening existentials.
Aside from that issue, there was also some discussion of whether the proposal should retain the ability to open existentials more freely within a function, such as by binding them explicitly to a variable with an opaque type like let x: some P = existentialP
and/or leaving the results of function calls with opened existentials open and unerased for further processing. The authors removed these aspects from the proposal out of concerns for adding too much complexity to the language all at once. Future proposals could still introduce local existential opening.
Thanks to everyone who participated in the review!