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-10617] polymorphism breaks when a generic instantiates its protocol-constrained parameterized type #53017

Closed
mattneub opened this issue May 4, 2019 · 3 comments
Labels
compiler The Swift compiler in itself improvement

Comments

@mattneub
Copy link

mattneub commented May 4, 2019

Previous ID SR-10617
Radar None
Original Reporter @mattneub
Type Improvement
Status Resolved
Resolution Duplicate

Attachment: Download

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Improvement
Assignee None
Priority Medium

md5: 72ae27299474e7069fe775e313aeac52

duplicates:

  • SR-10285 Subclass of a class that conforms to a protocol and extends NSObject is not instantiate correctly

Issue Description:

This came up on Stack Overflow. There are some complications that I'll get to in a moment; because of those complications, I am uncertain what the bug is or whether there's a bug. I just know that I'm surprised.

In the following playground code, a generic class, Wrapper, is asked to instantiate its parameterized type. The type is resolved explicitly to B, a subclass of A. In Xcode 9.2, it instantiates B, as expected. But in Xcode 10.2.1 the generic instantiates A instead.

protocol P {
    init()
    func doThing()
}
class Wrapper<T:P> {
    func go() {
        T().doThing()
    }
}
class A : NSObject, P {
    required override init() {}
    func doThing() {
        print("A")
    }
}
class B : A {
    required override init() {}
    override func doThing() {
        print("B")
    }
}
Wrapper<B>().go()

The result is that we print B in Xcode 9.2 but we print A in Xcode 10.2.1. I find that result so unbelievable that I have included screen shots to prove it.

Now for the further complications. The following remarks apply to Xcode 10.2.1.

  • The involvement of the protocol, which constrains the parameterized type, is crucial. If we constrain the generic type to A with Wrapper<T:A> instead of Wrapper<T:P>, we get B instead of A.
  • Or, if we keep Wrapper<T:P> but we change the protocol P declaration to @objc, we get B instead of A.
  • Or, if we don't make P @objc, but we eliminate class A's inheritance from NSObject (and the word override from A's init declaration), making A a base class, we get B instead of A.

These considerations suggest that the involvement of Objective-C is central somehow.

@hamishknight
Copy link
Collaborator

This looks like [SR-10285], and is fixed on master with a cherry-pick for 5.1.

@mattneub
Copy link
Author

mattneub commented May 6, 2019

@hamishknight Thanks!

@mattneub
Copy link
Author

mattneub commented May 7, 2019

@hamishknight So it turns out this is right there in the release notes (https://developer.apple.com/documentation/xcode_release_notes/xcode_10_2_1_release_notes) and that yet another way to work around this issue is to mark A's init as @nonobjc.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler The Swift compiler in itself improvement
Projects
None yet
Development

No branches or pull requests

2 participants