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-9645] Convenience inits unsoundly allow calling factory inits #52089

Open
belkadan opened this issue Jan 12, 2019 · 2 comments
Open

[SR-9645] Convenience inits unsoundly allow calling factory inits #52089

belkadan opened this issue Jan 12, 2019 · 2 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself

Comments

@belkadan
Copy link
Contributor

Previous ID SR-9645
Radar None
Original Reporter @belkadan
Type Bug
Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug
Assignee None
Priority Medium

md5: b52c428950ae7b584dcb51a368f527bc

relates to:

  • SR-5255 Make this initialization pattern efficient

Issue Description:

@import Foundation;
@interface Foo : NSObject
+ (nonnull Foo *)fooWithPowerLevel:(NSInteger)level;
@end
@interface Bar : Foo
@end
@implementation Foo
+ (nonnull Foo *)fooWithPowerLevel:(NSInteger)level {
  (void)powerLevel; // hey, it's just an example
  return [[Foo alloc] init];
}
@end
@implementation Bar
@end
extension Foo {
  convenience init(overNineThousand: Bool) {
    // Uh oh!
    self.init(powerLevel: overNineThousand ? 9001 : 2)
  }
}

print(Bar(overNineThousand: true)) // creates a Foo!

A "non-convenience factory initializer" is a factory initializer that can't be inherited. You can't define these in Swift, but you can in Objective-C (by specifying an explicit return type instead of using instancetype). Swift's convenience initializers are inherited (as are Objective-C's), and so they shouldn't be allowed to delegate to non-convenience factory initializers (unless the class is final).

However…fixing this would be a source-breaking change, and we don't currently have a way to define what people want in Swift (a non-inherited factory initializer). Meanwhile, everything works fine if they only use the convenience initializer on the original class.

If we don't think we're going to get factory initializers in Swift soon, we should consider adding a run-time check that the Self type matches the type the factory initializer is going to create.

@belkadan
Copy link
Contributor Author

Note: this "works" in Swift 4.2 mode and fails the SIL verifier in Swift 5 mode.

@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
Projects
None yet
Development

No branches or pull requests

1 participant