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-7783] Cannot subclass NSString due to ExpressibleByStringLiteral initializer #3691

Open
michelf opened this issue May 26, 2018 · 5 comments

Comments

@michelf
Copy link

michelf commented May 26, 2018

Previous ID SR-7783
Radar rdar://problem/40636610
Original Reporter @michelf
Type Bug
Additional Detail from JIRA
Votes 1
Component/s Compiler, Foundation
Labels Bug
Assignee None
Priority Medium

md5: 7ca07235bdf43a633e747405b099e091

Issue Description:

Normally, you can't add conformance to `ExpressibleByStringLiteral` in a class extension for a non-final class. But somehow Foundation manages to do it. As a consequence, you can't create a subclass of `NSString` or `NSMutableString` because you can't override the required initializer because it comes from an extension.

If you write this:

class C: NSString {
    override init() { super.init() }
}

You get fix-its telling you to add these:

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
required init?(pasteboardPropertyList propertyList: Any, ofType type: NSPasteboard.PasteboardType) {
    fatalError("init(pasteboardPropertyList:ofType:) has not been implemented")
}
required convenience init(stringLiteral value: StaticString) {
    fatalError("init(stringLiteral:) has not been implemented")
}

But there's no way to get the last one to compile because:

"Overriding declarations in extensions is not supported"

Xcode 9.3 (9E145)

@belkadan
Copy link

If you override all of NSString's designated initializers, you'll be able to inherit the required convenience initializer.

@michelf
Copy link
Author

michelf commented May 29, 2018

While the following works for NSString:

class C: NSString {

   override init() { fatalError() }
   required init?(coder aDecoder: NSCoder) { fatalError() }

   required init?(pasteboardPropertyList propertyList: Any, ofType type: NSPasteboard.PasteboardType) { fatalError() }

}

It doesn't work when subclassing NSMutableString.

class D: NSMutableString {

override init() { fatalError() }
required init?(coder aDecoder: NSCoder) { fatalError() }

required init?(pasteboardPropertyList propertyList: Any, ofType type: NSPasteboard.PasteboardType) { fatalError() }

}

'required' initializer 'init(stringLiteral🙂' must be provided by subclass of 'NSString'

@belkadan
Copy link

NSMutableString adds init(capacity:)…and doesn't mark it as a designated initializer, which means init() is still needed as well. (Also, that AppKit one makes me very sad. That's a bug we probably can't fix.)

The compiler-side change here is probably to add a note about why init(stringLiteral:) can't be inherited, i.e. listing the designated initializers that haven't been overridden.

@michelf
Copy link
Author

michelf commented May 30, 2018

Agree. Offering a fix-it with the missing designated initializers would be great. They're hard to find because they can be scattered in many places.

@belkadan
Copy link

@swift-ci create

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@shahmishal shahmishal transferred this issue from apple/swift May 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants