Allowing type conversion from final class to Self

I dug around to see if there was already an SR for this, but couldn't find any. Should the following code be allowed:

final class C {
    static func foo() -> Self {
        return C() // error: Cannot convert return expression of type 'C' to return type 'Self'

    private init() {}

It seems like the compiler should be able to prove that if C is final then C and Self will always be the same type. Is there an issue here that I'm missing?


Yeah, that looks like a bug. Self and the concrete type ought to be equivalent in a final class. cc @Slava_Pestov

1 Like

I opened a PR in March to fix the use of Self inside class bodies, but then got busy and forgot about it. I'll try to get back to it soon and address Slava's comments.


This shouldn't be an error, but should be a warning?

return self.init() is how you would have to do it in any other case, and is more resilient to refactoring.

Maybe more of a style preference, but seems worth considering.

No, it shouldn’t. A final class is no different from a struct in this respect.


My point isn't about Type semantics. Since it's returning Self, using self.init is more consistent and maintainable. E.g. if you remove final from the class, self.init would remain valid, while C() would break. And everywhere else where you're returning Self, you can't use a concrete Type.

Again, may fall under style preference.

I'm not sure what you mean here. Self is a shorthand for the containing type if that type is a struct, enum, or final class. This is the subject of SE-0068. What is reported here is straightforwardly a bug.

As a matter of API design, final is a, well, final decision—you can't revoke it without breaking compatibility with your clients.


I totally forgot about your PR! Since you last worked on it, John Hasworth finished off SE-0068 with a new implementation, and I did some follow-up fixes. I think it it should be complete now -- can you double check that your tests now pass with the latest code on master?

1 Like

Yeah, I agree that they should be equivalent for a final class, but currently are not. We still have to mangle them differently, though -- existing frameworks might have final classes with methods that return Self. Also, in addition to allowing a type conversion we have to revisit the method override matching rules, since we probably also want a method that returns a concrete type to be able to override a method returning Self as long as the override is in a final class. @Jumhyn feel free to go ahead and file an SR for this. If we find a dupe we can always dupe them later. Better to be safe than sorry :)


Done, filed as SR-11414!