swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.49k stars 10.35k forks source link

[SR-2348] Compiler crash or error when conforming Objective-C generic type to `Sequence` #44955

Open e2652f27-fdca-469d-a3e9-bf38e5bd1773 opened 8 years ago

e2652f27-fdca-469d-a3e9-bf38e5bd1773 commented 8 years ago
Previous ID SR-2348
Radar None
Original Reporter @jadengeller
Type Bug
Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 0 | |Component/s | Compiler | |Labels | Bug, CompilerCrash | |Assignee | None | |Priority | Medium | md5: c38dcabc918890090a9425541ab5131a

Issue Description:

Currently, conforming an Objective-C generic type to `Sequence` is not possible in Swift. I think that the problem may be more general in that you cannot conform to a protocol with associated types, but I'm unsure.

Here's a recreation of the problem: https://gist.github.com/JadenGeller/6672c8a55600f2ce415bcf60da6dd24a

belkadan commented 8 years ago

@slavapestov, have we seen this before?

e2652f27-fdca-469d-a3e9-bf38e5bd1773 commented 8 years ago

It's almost entirely impossible to write extensions on Objective-C generic types in Swift. For example, I can't write `addObjectsFromSequence` as an extension on `NSArray` without accessing the generic type. And even some methods that seem like they wouldn't require runtime knowledge of the generic type are not possible to write.

e2652f27-fdca-469d-a3e9-bf38e5bd1773 commented 8 years ago

Might be a duplicate of https://bugs.swift.org/browse/SR-1779

belkadan commented 8 years ago

cc @jckarter, although really I think those (valid) complaints deserve a separate bug from this crash.

slavapestov commented 8 years ago

Yeah, I think it's a dupe of SR-1779. We need to store the type parameters in the conformance for Objective-C generic types.

jckarter commented 8 years ago

This is a more specific problem than SR-1779. Returning IteratorOfOne<Any> makes the method @nonobjc, since IteratorOfOne isn't representable in ObjC, and we conservatively assume that all @nonobjc declarations require real type metadata.

jckarter commented 8 years ago

However, trying to work around that does reveal a different compiler crash:

@import Foundation;

@interface Box<T> : NSObject
@property (nonatomic) T _Nonnull value;
@end

struct BoxIterator {
  id __unsafe_unretained _Nullable value;
};
extension Box: Sequence {
    public func makeIterator() -> BoxIterator {
        let unmanagedSelf = Unmanaged.passRetained(self as AnyObject)
        return BoxIterator(value: unmanagedSelf.autorelease())
    }
}

extension BoxIterator: IteratorProtocol {
  public mutating func next() -> Any? {
    let result = self.value
    self.value = nil
    return result
  }
}
jckarter commented 8 years ago

The fixes in https://github.com/apple/swift/pull/4324 should at least allow you to conform to a protocol using @objc methods.