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

WIP SR-1715: require superclass to have a designated initializer #14024

Conversation

randomstep
Copy link

Description

After checking the superclass in other ways, this PR verifies that the superclass has at least one designated initializer. Classes like NSProxy do not have a designated init, and thus are not sub-classable / instantiatable from Swift. The current error is lacking, and this PR provides a more targeted error.

Bug Link

Resolves SR-1715.

Questions before running CI

Before CI is run, I'd like any PR feedback. Specifically:

  • The tests seem clearly in the wrong place to me. Something like "super_constructor.swift" seems like a better place, but is not importing Foundation. I could add it, or I could add a new test file. Not sure I should. Will look for more init tests that my tests might better fit.
  • while fixing tests, an apparently unrelated test started failing. It has to do with checking sil instructions. I may have changed the A class in the test version of Foundation (by adding an init), and that may have changed some assumptions. I am not sure where to even start figuring this out. It does appear to be Swift 2 syntax still in the test, so I could at least clean that up (duplicate labels and similar).
  • A number of tests needed updates as they failed this new check. I added inits to some non-Swift objects, and expected errors in some other places. Currently not sure how to handle the circular dependency test failure though. They clearly should show the user the circular errors, not the less-specific (and un-useful) designated-init error. I was unable to fix one of the circularity errors. I'd love to know that a type was part of a cycle, in which case this new check could be skipped entirely. Maybe more of the super checks should be skipped in that case? As a worst-case, might it be acceptable to document the failing test to also expect this new error? My take: we should avoid that if at all feasible.
  • Style: the bools in this file are mixed on whether they start upper or lower case. I tried to match the style my code was closest to, so my bools are camelCase. Should they be TitleCase instead?
  • I also looked at adding a related test in "accessibility.swift" (code below). But after some thought, I think that is more in the court of SR-2484 and should probably be a separate PR at a minimum. Let me know if you think this should be covered under this PR instead. Here is that test code:
// SR-1715: no available designated initializers
class Base {
	private init() {}
}

class SubClass: Base { // expected-error {{'cannot inherit from class 'Base' because it has no designated initializers'}}
}
  • as a separate commit, I'm also considering refactoring the entire visit function this lives inside. Probably not necessary or desired, but if I'm wrong, let me know. (Things like de-nesting from the ifs with inverse statements, extracting some of the large work chunks to separate functions.)

Step Christopher added 2 commits January 19, 2018 11:29
Tests should probably live somewhere else, not satisfied with
options I have found so far.

Handles case where super has initializers but not
designated initializers, throws a better error. (This
might be possible to collapse with other code already
throwing this error. Have not yet pursued that.)

Numerous tests also need updating to have valid
superclasses, those changes follow in a separate
commit.

Explicitly checks super invalidity.
Worth asking - should that bool be set by/from
the circularity check somehow,
since it replaces a super with an error type?
Non-Swift classes need a valid init method to be subclassable
from Swift. New error handling pointed out problems with these
tests.
The new error will also require new tests ensure that Obj-C types
have an init method if they are subclassed in Swift.
There are a few failing tests still, but this commit fixes up most
failures caught by the new error.
if (!isInvalidSuperclass && !Super->isInvalid()) {
bool superIsConstructible = false; // can be satisfied by convenience initializers
bool superHasDesignatedInitializer = false; // is subclassable
for (auto member : Super->getMembers()) {

Choose a reason for hiding this comment

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

Copy link
Author

Choose a reason for hiding this comment

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

Might work. I'd like to find a refactor that cleans this up for sure.

Copy link
Collaborator

@xwu xwu left a comment

Choose a reason for hiding this comment

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

Hurray! Just some formatting comments.

@@ -2002,6 +2002,9 @@ ERROR(inheritance_from_cf_class,none,
ERROR(inheritance_from_objc_runtime_visible_class,none,
"cannot inherit from class %0 because it is only visible via the "
"Objective-C runtime", (Identifier))
ERROR(inheritance_from_class_with_no_designated_initializers,none,
"cannot inherit from class %0 because it has no designated initializers",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Drive-by nit: spaces, not tabs, are used in this file; please align this line as shown above.

// Require the superclass to have an available designated initializer,
// unless we have already determined the class or superclass is invalid.
if (!isInvalidSuperclass && !Super->isInvalid()) {
bool superIsConstructible = false; // can be satisfied by convenience initializers
Copy link
Collaborator

Choose a reason for hiding this comment

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

Another nit: all comments are capitalized and punctuated, and this file respects the 80-character limit for each line.

@CodaFi
Copy link
Contributor

CodaFi commented Nov 21, 2019

@randomstep Are you still interested in this patch? If so, please rebase it and address the review comments. Otherwise, we can close it out and I can update the SR to point another contributor at this work to see if they can take it over the goal line.

Thanks!

@CodaFi
Copy link
Contributor

CodaFi commented Jan 28, 2020

Alright, there hasn't been any movement or response here in a while. I'm going to close this out and discharge the SR assignment. If you wish to pursue this change further, please reopen this pull request, rebase it, and address the review feedback.

Thanks!

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.

4 participants