Status of subclass existentials

Evolution proposal 0156 for Subclass Existentials has been mostly implemented in Swift 4, however there are few cases where the examples in the proposal are supposed to be okay, but actually produce errors in Swift 4.1. Are these going to be implemented or are they going to be errors in the future as well?

4. If a protocol composition contains two class types....

protocol P {}
class C {}
class D : C { }
class E : C { }
class F : D, P { }

let t: C & D & P = F() // Okay: F is a subclass of D and conforms to P
// error: protocol-constrained type cannot contain class 'D' because it already contains class 'C'

let u: D & P = t       // Okay: D & P is equivalent to C & D & P
// error: value of type 'C & P' does not conform to specified type 'D & P'

let v: C & D & P = u   // Okay: C & D & P is equivalent to D & P
// error: protocol-constrained type cannot contain class 'D' because it already contains class 'C'

5. When a protocol composition type contains one or more typealiases, ...

Similarly to 4, the examples TA7 and TA8 produce similar errors.

https://github.com/apple/swift-evolution/blob/master/proposals/0156-subclass-existentials.md

Could you please file a bug for this? IMO the correct behavior here is to warn about a redundant component, the same way we do with requirements:

func foo<T>(_ arg: T) where T: C, T: D {} // Redundant superclass constraint 'T' : 'C'

@Moximillian is quoting from SE-0156, which explicitly states that this usage should be OK.

I understand. This is my opinion - they are redundant anyway. This can be discussed therein, the bug is worth filing at least because the error is shown.

Sure, but the matter has already been settled.

It is never late to overlook the details or propose to do so. I had not yet joined the community when 0156 was being implemented, so I haven't had a chance to participate in the discussion.
I already have an issue about other similar cases: SR-7405.

You seem to strictly agree these redundancies shouldn't produce warnings. Why?

I really don't have an opinion on the matter. I'm just calling your attention to the fact that there is a particular behavior, different from what you think it should be, which has already been explicitly approved as the intended one for Swift. Therefore, absent new proof that it's actively harmful, it's not up for revisiting.

The reason I didn't implement this is that it is difficult in the current type checker design. It requires fully resolving the superclass chain of any class terms in a subclass existential when we realize the existential type. This is because we have to find their common superclass, if any. Such circularities are difficult to deal with right now so I didn't want to introduce any new ones.

Also this kind of thing seemed to have marginal benefit. Is it important for your use case?

One missing part of the proposal that I'm more keen on implementing is protocols with class constrained Self:

protocol P where Self : UIView { ... }

Right now this doesn't work properly. I'd like to fix it at some point in the future.

4 Likes

Please keep in mind I am aware of the review cycle. More importantly, I'm absolutely sure there is no 'is not up for revisiting'.
..Which is why hearing that from you is a bit of a surprise for me. It should be clear the majority of applied changes to the language that aren't bug fixes or purely additive, including amendments to proposals, would be subject to your last sentence together with the evolution category of this community. Obviously that makes no sense.

2 Likes

I do not have specific use case or need where these error-producing existentials are used. However, I really don't want to see half-implemented approved proposals, as they should be good references to how you can use Swift in practise.

So, I'd like to see either of two actions being done to rectify the current situation:

  1. decide that the approved proposal 0156 is not intended to be fully implemented => change 0156 to reflect the current implementation.
  2. agree that 0156 reflects the correct intention with the expectation that 0156 will be fully implemented some day => bug could be filed to track the remaining implementation
1 Like

Redundant requirements of the same flavor that do receive warnings i.e. T: Class, T: SubClass should require resolving the chain as well. Is a logic correlation here possible if it really is difficult?

The point is that currently approved proposal states that there should be no warning nor an error. So a bug fix that changes an error to an warning is incorrect way to fix it.

If it is desired that it actually should produce an error or a warning, then the proposal has to be changed first, before creating bugs.

I have already mentioned that I understand it is supposed to show nothing according to the proposal. I don't see changing it to a warning as something that should go through another review. However, to decide on that, we first need to make it work (make it possible to get rid of the error). The bottom line is that currently it doesn't, which is why I am encouraging you to file a bug. Even if we can't tackle it at present, we will at least have a reference of what to deal with.

2 Likes

I added this thread to your bug (SR-7405).

This is an artifact of the current evolution process. I see them more as aspirational documents that define the direction of the implementation but don't specify it precisely. If you compare the level of rigor in a typical Swift evolution proposal with, say, the TC39 JavaScript standards process, you will see what level of detail is required before full fidelity can be reasonably expected between the specification and implementation.

As for this specific issue my preference would be to amend SE-0156 to remove this behavior where we find the common superclass ancestor in the case of redundancy. If nobody can come up with a reasonable use-case for writing such code, there is no need to pay the opportunity cost of updating the implementation to match the proposal.

1 Like

Fair enough, I thought that since the approval process nowadays requires implementation to be provided, that the proposals would more or less match the implementation, especially when they are marked as "implemented" as is the case for the 0156 proposal.

At the very least it would be nice to have bugs that track the unimplemented parts of the proposals, if such remain, (maybe SR-8151 for this case), as well as referring to those bugs in the proposal to get better understanding of the current state. Would it be ok to create PR to update the proposal bug links?

Another related bug report: [SR-8151] Class inheriting from class existential behaviour doesn't match SE-0156 · Issue #50683 · apple/swift · GitHub

1 Like

FWIW SE-0156 was accepted before the rule was introduced, and I only started work on the implementation after the review had concluded.