Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-8153] Can no longer inherit from a typealias'd protocol composition containing AnyObject #50685

Open
hamishknight opened this issue Jun 29, 2018 · 6 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself regression swift 4.0 type checker Area → compiler: Semantic analysis

Comments

@hamishknight
Copy link
Collaborator

Previous ID SR-8153
Radar None
Original Reporter @hamishknight
Type Bug
Status Reopened
Resolution
Environment

Apple Swift version 3.1-dev (LLVM 9cb6a3ccee, Clang f38438fc01, Swift b5b79f8)
Target: x86_64-apple-macosx10.9

Apple Swift version 4.1.2 (swiftlang-902.0.54 clang-902.0.39.2)
Target: x86_64-apple-darwin17.6.0

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, 4.0Regression, TypeChecker
Assignee None
Priority Medium

md5: 8a66f8482ae9d01a49d646d0c08030b5

Issue Description:

In Swift 3.1, it was possible to inherit from a protocol composition containing AnyObject through a type alias:

protocol P {}
typealias X = protocol<P, AnyObject>
class C : X {} // okay

However in Swift 4, both the above example in Swift 3 mode and the equivalent Swift 4 spelling no longer compile (presumably due to the fact that AnyObject is no longer an actual protocol):

protocol P {}
typealias X = protocol<P, AnyObject>
class C : X {} // error: Inheritance from non-protocol, non-class type 'X' (aka 'P & AnyObject')
protocol P {}
typealias X = P & AnyObject
class C : X {} // error: Inheritance from non-protocol, non-class type 'X' (aka 'P & AnyObject')

I would argue that this is a useful feature to have – being able to have a list of protocol constraints in a typealias along with the requirement of being a class, and then being able to directly conform a class to this typealias.

Especially given the fact that this is legal:

class A {}
typealias X = A & AnyObject
class C : X {} // okay
@belkadan
Copy link
Contributor

belkadan commented Jul 2, 2018

Seems reasonable to me as well. @slavapestov, what do you think?

@slavapestov
Copy link
Member

@DougGregor added a Swift 3 compatibility hack but it's still an error in Swift 4 mode. I'd rather it was an error too, otherwise you can write confusing and redundant things like "class Foo : AnyObject {}".

@DougGregor
Copy link
Member

The error was intentional, and I think we should keep it. The superclass of a class is the single most important aspect of its definition, and should be called out explicitly, rather than buried behind a protocol composition. This same logic is why the superclass needs to be written first in the comma-separated list.

@hamishknight
Copy link
Collaborator Author

I agree regarding the superclass having to be stated explicitly in the inheritance clause, I filed SR-8151 for that. But I still think it's reasonable to state a conformance to a protocol composition that happens to contain AnyObject (furthermore I think that class C : AnyObject should be a warning rather than an error).

But if we are to continue rejecting these, should we also reject struct S : Any? I'm currently working on implementing a warning for it over at #17425 which I guess could be used to stage it in to an error if desired.

@DougGregor
Copy link
Member

I agree that it makes sense to state conformance to a protocol composition that contains ``AnyObject``, or even a class bound--so long as the class satisfies the class bound. For example, we currently error on this:

protocol P { }
class C { }
typealias CP = C & P
class D: C { }
class E: D, CP { } // error: multiple inheritance from classes 'D' and 'C'

which seems wrong to me: the superclass is "D" (it's right there in the correct place!), and we should be checking that E inherits from C.

Now, I think it's reasonable to warn if a particular type in the list doesn't contribute anything, so "struct S: Any" and "class C: AnyObject" are reasonable to warn about, because "Any" and "AnyObject" contribute no information... but that's not an error, that's a "you did something meaningless, are you sure that's what you meant?" warning.

@slavapestov
Copy link
Member

Re-opening based on Doug's response.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself regression swift 4.0 type checker Area → compiler: Semantic analysis
Projects
None yet
Development

No branches or pull requests

5 participants