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-746] Objective-c subclass unimplemented initializer #43361

Closed
swift-ci opened this issue Feb 16, 2016 · 11 comments
Closed

[SR-746] Objective-c subclass unimplemented initializer #43361

swift-ci opened this issue Feb 16, 2016 · 11 comments
Labels
compiler The Swift compiler in itself crash Bug: A crash, i.e., an abnormal termination of software good first issue Good for newcomers improvement PrintAsClang Area → compiler: The PrintAsClang library run-time crash Bug → crash: Swift code crashed during execution

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-746
Radar None
Original Reporter Torsph (JIRA User)
Type Improvement
Status Resolved
Resolution Done
Additional Detail from JIRA
Votes 1
Component/s Compiler
Labels Improvement, PrintAsObjC, RunTimeCrash, StarterBug
Assignee Torsph (JIRA)
Priority Medium

md5: 00cfa5be4152aa8f7bb3c422b0b71fb2

Issue Description:

When using swift code from objective-c the following code will crash runtime with this error:
"fatal error: use of unimplemented initializer 'init(type: )' for class 'TestProject.SomeSubClass'"

public class SomeBaseClass: NSObject {
    public let type: String

    public init(type: String) { self.type = type }
}

public class SomeSubClass: SomeBaseClass {
    let otherValue: String

    public init(otherValue: String) {
        self.otherValue = otherValue
        super.init(type:"someType")
    }
}

Generated -swift.h file:

SWIFT_CLASS("_TtC17TestProject13SomeBaseClass")
@interface SomeBaseClass : NSObject
@property (nonatomic, readonly, copy) NSString * __nonnull type;
- (nonnull instancetype)initWithType:(NSString * __nonnull)type OBJC_DESIGNATED_INITIALIZER;
@end

SWIFT_CLASS("_TtC17TestProject12SomeSubClass")
@interface SomeSubClass : SomeBaseClass
- (nonnull instancetype)initWithOtherValue:(NSString * __nonnull)otherValue OBJC_DESIGNATED_INITIALIZER;
@end

This happens because both the parent and subclass init method is accessible from objective-c.

Possible solutions:

  1. the compiler should report a error/warning about missing initializers
  2. the generated -swift.h file should state that the subclass hasn't implemented the super class init method.
  3. the subclass could inherit the superclass initializers
@belkadan
Copy link
Contributor

This is correct behavior. In Swift, a subclass is not required (or expected) to inherit its superclass's initializers, whereas in Objective-C it usually is. The best we can do is crash at runtime.

…well, actually, I suppose we could do better by marking the initializer unavailable in the subclass in the generated header.

@swift-ci
Copy link
Collaborator Author

Comment by Thomas Torp (JIRA)

I expected it to be the correct behavior 🙂 But as you said it would be really great if the initializer is unavailable in the subclass 🙂

@sveinhal
Copy link

sveinhal commented Jun 9, 2016

I think the generate header file should look like this:

SWIFT_CLASS("_TtC17TestProject13SomeBaseClass")
@interface SomeBaseClass : NSObject
@property (nonatomic, readonly, copy) NSString * __nonnull type;
- (nonnull instancetype)init __unavailable;
- (nonnull instancetype)initWithType:(NSString * __nonnull)type OBJC_DESIGNATED_INITIALIZER;
@end

SWIFT_CLASS("_TtC17TestProject12SomeSubClass")
@interface SomeSubClass : SomeBaseClass
- (nonnull instancetype)init __unavailable;
- (nonnull instancetype)initWithType:(NSString * __nonnull)type __unavailable;
- (nonnull instancetype)initWithOtherValue:(NSString * __nonnull)otherValue OBJC_DESIGNATED_INITIALIZER;
@end

@sveinhal
Copy link

sveinhal commented Jun 9, 2016

Also every function that is marked as private override should be explicitly attributed as __unavailable in the generates header file.

@belkadan
Copy link
Contributor

belkadan commented Jun 9, 2016

You can't mark something private override for exactly that reason. You're not allowed to violate Liskov substitutability ("a subclass can be used where the superclass is expected") at compile-time except by using @available. I don't think we print @available either, though.

@belkadan
Copy link
Contributor

belkadan commented Jun 9, 2016

I agree with the general pattern, though I would add a message to the unavailable attribute.

@sveinhal
Copy link

Yeah, sorry, I meant every initializer marked as private override should be __unavailable. A message is fine.

@lilyball
Copy link
Mannequin

lilyball mannequin commented Jul 29, 2016

What message should go with the unavailable attribute? I'm not able to come up with anything that adds anything meaningful beyond the default "'foo' is unavailable". We certainly can't suggest a different initializer because the compiler doesn't know what other initializer would be appropriate as a suggestion.

@lilyball
Copy link
Mannequin

lilyball mannequin commented Jul 29, 2016

Submitted as PR #3852.

@swift-ci
Copy link
Collaborator Author

Comment by Thomas Torp (JIRA)

Eridius (JIRA User) I feel that unavailable message is the right choice. Thanks for solving this issue 🙂

@lilyball
Copy link
Mannequin

lilyball mannequin commented Aug 1, 2016

Merged in 0473e99.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@AnthonyLatsis AnthonyLatsis added the crash Bug: A crash, i.e., an abnormal termination of software label Dec 12, 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 crash Bug: A crash, i.e., an abnormal termination of software good first issue Good for newcomers improvement PrintAsClang Area → compiler: The PrintAsClang library run-time crash Bug → crash: Swift code crashed during execution
Projects
None yet
Development

No branches or pull requests

4 participants