Skip to content

Sema: Improve redeclaration error for synthesized inits #24090

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

Merged
merged 3 commits into from
Apr 19, 2019

Conversation

AnthonyLatsis
Copy link
Collaborator

Resolves SR-8021.

@jrose-apple

Copy link
Contributor

@jrose-apple jrose-apple left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for picking this up!

@@ -667,6 +667,9 @@ ERROR(reserved_member_name,none,
" 'foo.%1' expression", (DeclName, StringRef))

ERROR(invalid_redecl,none,"invalid redeclaration of %0", (DeclName))
ERROR(invalid_redecl_synth_init,none,
"invalid redeclaration of synthesized "
"%select{default|memberwise}1 %0", (DeclName, bool))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually use the term "default initializer" for a no-argument initializer? Unlike in C++, it's not the "default" if you don't initialize something. It might be fine just to leave out the qualifier in that case.

Copy link
Collaborator Author

@AnthonyLatsis AnthonyLatsis Apr 17, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to call "default" a synthesized no-argument initializer, but I guess we really don't formally have that term in Swift.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I stand corrected, and it makes sense if it only refers to the synthesized one.

@AnthonyLatsis AnthonyLatsis force-pushed the synth-init-conflict-diag branch from 64f15f6 to d383624 Compare April 18, 2019 09:21
@AnthonyLatsis
Copy link
Collaborator Author

AnthonyLatsis commented Apr 18, 2019

So I've gone a bit further with the second commit disabling redeclarations for inherited inits when they conflict with the implicit one. The reason for this is that the redeclaration error here always intersects with a more productive "cannot override in extension"or equally misleading error.

// have already taken care of emitting a more productive diagnostic.
if (isa<ConstructorDecl>(other) && other->isImplicit() &&
other->getOverriddenDecl())
continue;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm concerned by this not requiring any changes to existing tests, and I don't think your new test covers it. What if the inherited initializer is exposed to Objective-C?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I'm not sure exiting early is a good idea, because we still need to mark one of them invalid.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sema, Constraints, decl and Generics pass just fine, but it might affect something elsewhere.

and I don't think your new test covers it. What if the inherited initializer is exposed to Objective-C?

You're right, I'll add some more tests with @objc and dynamic. Right now though it boils down to 'init(arg:)' has already been overridden with and without the change if I plug all the errors.

@AnthonyLatsis AnthonyLatsis force-pushed the synth-init-conflict-diag branch from d383624 to a452995 Compare April 18, 2019 18:23
This can only happen when the conflicting init is within an extension.
It is the override checker's responsibility to emit a sensible diagnostic here.
@AnthonyLatsis AnthonyLatsis force-pushed the synth-init-conflict-diag branch from a452995 to 78f4b9d Compare April 18, 2019 19:04
@AnthonyLatsis
Copy link
Collaborator Author

AnthonyLatsis commented Apr 18, 2019

Concerning the has already been overridden error – I have no idea if there is a use case, but should we allow to override an @objc dynamic designated init with a convenience init in an extension? An analogy with a method is apparently possible.

@jrose-apple
Copy link
Contributor

Unfortunately I think that's legal, but not if the initializers have already been inherited. In this case, though, source compat is probably the deciding factor. What does Swift 5.0 do?

@AnthonyLatsis
Copy link
Collaborator Author

AnthonyLatsis commented Apr 18, 2019

What does Swift 5.0 do?

When I try to override one? 'init' has already been overridden (it still synthesizes the override). I added a test for that, by the way.

P.S. I don't have a fresh build though; this is a February master and Xcode 10.2 beta 2.

Copy link
Contributor

@jrose-apple jrose-apple left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, this looks good, then. Thanks, @AnthonyLatsis!

@jrose-apple
Copy link
Contributor

@swift-ci Please smoke test

@jrose-apple
Copy link
Contributor

@swift-ci Please test source compatibility

@jrose-apple jrose-apple self-assigned this Apr 18, 2019
@jrose-apple
Copy link
Contributor

@swift-ci Please test source compatibility

@AnthonyLatsis
Copy link
Collaborator Author

Thank you for guiding me through this!

Just in case there was a misunderstanding:

class A {
  @objc dynamic init(arg: Int) {}
}
class B: A {}
extension B {
  convenience override init(arg: Int) {} // 'init(arg:)' has already been overridden
}

I was pondering solutions to the "already overridden" diagnostic (which isn't great in this case), and then realized it might be legal to simply allow the override to follow, since the same can be done to a method. Hence the question earlier /.

@jrose-apple
Copy link
Contributor

Oops. Can you add -enable-objc-interop -disable-objc-attr-requires-foundation-module to the RUN line for this test, so that it'll work on Linux?

@jrose-apple
Copy link
Contributor

@swift-ci Please smoke test

@jrose-apple jrose-apple merged commit 79bd38b into swiftlang:master Apr 19, 2019
@AnthonyLatsis AnthonyLatsis deleted the synth-init-conflict-diag branch February 3, 2021 05:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants