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-14761] Poor diagnostic on implicitly overriden init() #57111

Closed
typesanitizer opened this issue Jun 11, 2021 · 9 comments
Closed

[SR-14761] Poor diagnostic on implicitly overriden init() #57111

typesanitizer opened this issue Jun 11, 2021 · 9 comments
Assignees
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself good first issue Good for newcomers type checker Area → compiler: Semantic analysis

Comments

@typesanitizer
Copy link

Previous ID SR-14761
Radar rdar://problem/79179597
Original Reporter @typesanitizer
Type Bug
Status Closed
Resolution Done
Environment

Xcode 13 beta

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, StarterBug, TypeChecker
Assignee @typesanitizer
Priority Medium

md5: 18501160a0fd0ecc00b62a8c26b1593a

Issue Description:

import Foundation
open class C: NSObject {}
                    // ^ note: 'init()' previously overridden here
extension C {
    public override convenience init() {}
                             // ^ error: 'init()' has already been overridden
}

Pointing to the opening brace is not very helpful IMO to explain what is going on since there is no user-written override there.

@typesanitizer
Copy link
Author

@swift-ci create

@CodaFi
Copy link
Member

CodaFi commented Jun 14, 2021

Ah, true. This diagnostic needs a special case for when the compiler synthesizes overrides of designated initializers. Makes for a good starter bug, though.

@swift-ci
Copy link
Collaborator

Comment by Jevon Mao (JIRA)

theindigamer (JIRA User) I'm still learning Swift, and if you don't mind can you explain a bit? Is there some sort of implicit default initializer in class C? Why is overriding not allowed in the extension?

@typesanitizer
Copy link
Author

jevonmao (JIRA User), NSObject has an initializer which takes no arguments. https://developer.apple.com/documentation/objectivec/nsobject/1418641-init

IIUC this is a designated initializer, if you look at the docs there you'll see this

In a custom implementation of this method, you must invoke super’s Initialization then initialize and return the new object.

which matches how designated initializers work.

Designated initializers are supposed to be defined within the class declaration (there is an exception for @objc initializers but that creates other issues, and I think that can be ignored here), if you try to define them outside, you'll get an error. (try this with some example Swift code!)

What is happening here IIUC is that since there are no stored properties (you can try adding stored properties and you'll see an error about no initializers), the parent class's init() can also be directly used to initialize the subclass. Based on the error message, it seems like the compiler is synthesizing an init for the subclass C which just calls NSObject's init(), but I'm not sure if that is actually what is happening in practice. (@CodaFi can tell you more about this)

Extensions can be anywhere, including in downstream modules. Allowing overriding in extensions would mean that certain calls would be forced to use dynamic dispatch, since which functions will be called are not known at compile-time. This inhibits performing optimizations at compile-time, and creates runtime overhead due to lookup tables which need to patched (either at load time or lazily during the first run). (There are also more issues with "dirty memory" but let's not go into the weeds...) I'm not exactly sure which of these reasons was used originally, I suspect it's some combination, but if I were to guess, I would guess that having more compile-time optimizations for known calls is the most important reason.


What needs to happen to fix this bug, I think, is that when we issue an error related to "has already been overridden", we should do some kind of check whether the declaration that will be pointed to is actually present in the source code. If it was implicitly synthesized, then the note's wording should be changed to make it clear that it talking about an implicitly synthesized declaration.

@swift-ci
Copy link
Collaborator

Comment by Hanna Yakusevych (JIRA)

Is anyone working on this already? If not, I'd like to give it a shot

@typesanitizer
Copy link
Author

I don't think so, no. Please feel free to assign it to yourself and ask questions in case you need help with something. 🙂

@swift-ci
Copy link
Collaborator

swift-ci commented Jul 3, 2021

Comment by Jevon Mao (JIRA)

theindigamer (JIRA User) Thanks for the previous explanation, that made sense. I was experimenting with the sample error code above, and for some reason, I could not reproduce the same diagnostic in Xcode 12.5 Playground. Instead, it shows this:

import Foundation
class C: NSObject {}
extension C {
     public override convenience init() {}   
                                // ^ 'init()' has already been overridden 
}

I tried again in godbolt, and it gives another different diagnostic:

import Foundation

class C: NSObject {}

extension C {
    public override convenience init() {}                             
                               // ^ error: overriding declarations in extensions is not supported
}

I'm trying to learn this compiler stuff, am I misunderstanding anything? Can you explain?

@typesanitizer
Copy link
Author

I think the difference may be coming about because Godbolt is likely running on Linux, not macOS. So the -enable-objc-interop flag is turned off, leading to different type-checking behavior around NSObject compared to using Xcode on macOS. I'm not sure why Xcode playgrounds would be missing part of the error, but you could try to reproduce with a standalone file or a project.

@xedin
Copy link
Member

xedin commented Jul 15, 2021

Fixed by #38365 Thank you, hanyakus (JIRA User)!

@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
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself good first issue Good for newcomers type checker Area → compiler: Semantic analysis
Projects
None yet
Development

No branches or pull requests

4 participants