SE-0352 (second review): Implicitly Opened Existentials

Moderator note: this post was originally in the previous review thread and has been moved at the request of the author

The review period has ended, but since this is an ongoing discussion and there is no subsequent thread, I would like to put my opinion here.

I agree with @Jumhyn's point of view about as any P. I don't think it's fatal. But now I'm concerned, because users can run into this behavior from other sides. @Douglas_Gregor recently updated proposal about "Losing" constraints when type-erasing resulting values. From the discussion, the behavior is as following.

protocol P {
  associatedtype A
}
protocol Q {
  associatedtype B: P where B.A == Int
}
func getBFromQ<T: Q>(_ q: T) -> T.B { ... }
func eraseQAssoc(q: any Q) {
  let b = getBFromQ(q)
}

// then, user shave to use `as` coercion:
getBFromQ(q) as any P

However, what happens if there is another getP? I have no idea how the next code would work.

func getP<T: P>(_ p: T)
getP(getBFromQ(q) as any P)

If the compiler interprets this in a nice way it won't cause any compile error. If not, then, the user would get confused. Awfully, they gets another error when they remove as any P. Struggling, they will find the following code works fine, and they would start to write a bug report at this moment :memo:

let p = getBFromQ(q) as any P
getP(p)

In the case the compiler can behave in a nice way, then, I'm also curious how the following code works. In any case, this code must cause a compile error.

getP(getBFromQ(q) as any P as any P)

After all, I'm a bit doubtful about introducing as any P as coercion mechanism while it still works as normal cast mechanism. Not a strong opposition, though :thinking: