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-2708] Extending ObjC generics in Swift 3 does not compile #45312

Open
swift-ci opened this issue Sep 20, 2016 · 19 comments
Open

[SR-2708] Extending ObjC generics in Swift 3 does not compile #45312

swift-ci opened this issue Sep 20, 2016 · 19 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-2708
Radar None
Original Reporter courteouselk (JIRA User)
Type Bug
Environment

XCode Version 8.0 (8A218a)

Additional Detail from JIRA
Votes 11
Component/s Compiler
Labels Bug
Assignee None
Priority Medium

md5: 2fa4d679d5ba96de70dc71c058d5ab46

relates to:

  • SR-3328 Cannot extend PHFetchResult to conform to Sequence in Swift 3

Issue Description:

ObjC:

@interface MySet<T : id<NSCopying>> : NSObject
@end

Swift:

class Foo { }
struct Bar { }
    
extension MySet {
    func foo() -> Foo { return Foo() }
    func bar() -> Bar { return Bar() }
}

Both of the extension methods result in "Extension of a generic Objective-C class cannot access the class's generic parameters at runtime". However, neither really does anything like that (at least not explicitly).

@belkadan
Copy link
Contributor

@jckarter, we've seen this before, right?

@jckarter
Copy link
Member

Right now, there's an unfortunate restriction that the extension methods have to be @objc. I would expect func foo() -> Foo to work if Foo is made to inherit NSObject. Similarly, if Bar can be imported as a C struct instead of defined in Swift, then func bar() -> Bar ought to work with the compiler as currently implemented too.

@swift-ci
Copy link
Collaborator Author

Comment by Anton Bronnikov (JIRA)

So, is this something that should be fixed, or is it by design and should be just documented?

@jckarter
Copy link
Member

Probably both.

@swift-ci
Copy link
Collaborator Author

Comment by Mathew Huusko V (JIRA)

Also experiencing this (extensions that were compiling in Swift 2, stopped in Swift 3 now that the class's generics are being imported).

Two things that seem to make this rather serious..

  1. The funcs use generics (not the class's just in general), so adding @objc is not an option.
  2. Implementing -classForGenericArgumentAtIndex: isn't remedying it either, which is supposed to make the thing the false error is describing possible

@swift-ci
Copy link
Collaborator Author

Comment by Vasili Silin (JIRA)

Hi.

By my mind, I have similar issue.

Don't know how to add +1 to the issue.

Let me share code with you. I have class like this:

extension AWSTask {
    
    func continueWithCompletionSource<TResult : Mappable>(_ taskCompletionSource: TaskCompletionSource<TResult>) {
        self.continue({ (task: AWSTask) -> Any? in
            switch (task.error, Mapper<TResult>.map(task.result)) {
            case (let error, _) where error != nil:
                taskCompletionSource.trySet(error: error!)
                break
                
            case (nil, let result) where result != nil:
                taskCompletionSource.trySet(result: result!)
                break
                
            default:
                taskCompletionSource.trySet(error: NSError.unkownContinueTask)
                break
            }
            
            return nil
        })
    }

}

But it's not work in Swift 3, because AWSTask has generic param.

I use workaround for now, but hope it will be fixed in future.

Classes:
'AWSTask' from AWSCore
'TaskCompletionSource' from Bolts-Swift
'Mapper' from ObjectMapper

Best regards,
Vasili Silin.

@swift-ci
Copy link
Collaborator Author

Comment by Mathew Huusko V (JIRA)

In the meantime/for Swift 3, is there any way to prevent an Obj-C class with lightweight generics being imported as generic into Swift? With `__covariant` being ignored, and extensions not possible (thus not being able to replace NS_REFINED_FOR_SWIFT symbols), integration is rather tricky/it's more trouble than it's worth..

@swift-ci
Copy link
Collaborator Author

Comment by Mathew Huusko V (JIRA)

@jckarter @belkadan I'm curious if this issue (seems in generic Obj-C generics imports is less so buggy, and more just not finished yet) has been discussed anywhere else/there's any plan for it to make it into 3.1?

@jckarter
Copy link
Member

We can't promise that a fix is on the way, unfortunately. @rjmccall did propose a change to the model that might save us from having to enforce these annoying constraints on ObjC generic behavior—instead of saying that the generic metadata for the type-erased parameters is never available at runtime, Swift could act as if it always is, and make a best effort at propagating it as long as Swift is in control of calling conventions. When we pass through a C or ObjC interface that necessitates dropping the runtime type info, we can revert the erased type parameters to their upper bound type (AnyObject, NSCopying, or whatever protocol type). This should allow most code to just work; only things like dynamic casting to a generic parameter would potentially be affected.

@swift-ci
Copy link
Collaborator Author

swift-ci commented Nov 7, 2016

Comment by Michael Armstrong (JIRA)

+1 here, i've effectively "worked around" this by moving the offending code outside of an extension for now and into a standard class. commenting as I want to track the ticket.

@swift-ci
Copy link
Collaborator Author

swift-ci commented Feb 1, 2017

Comment by Jean-Luc Jumpertz (JIRA)

I get the same error when trying to extend NSHashTable with the Sequence protocol, in order to make enumeration of hashTables with for ... in loops possible.

extension NSHashTable: Sequence  {
    public func makeIterator() -> NSFastEnumerationIterator {
        return NSFastEnumerationIterator(self)
    }
}

In this case, the generic Obj-C class that cannot be extended is a standard Foundation class, which makes difficult to find satisfactory workarounds for this issue.

@swift-ci
Copy link
Collaborator Author

Comment by Derrick Ho (JIRA)

I'm experiencing this in Xcode 8.3
Are there any plans to fix this bug?

@swift-ci
Copy link
Collaborator Author

Comment by Hitesh Savaliya (JIRA)

Any updates on this bug, please?

I'm seeing similar issue `description` on extension of NSCache

let key = "ABC"
extension NSCache {
      override open var description: String {
                        if let value = self.object(forKey: key) { // Error: Extension of a generic Objective-C class cannot access the class's generic parameters at runtime
                        return value as String
                       }
      }

@jckarter
Copy link
Member

If you've moved to Swift 4, then you may need to explicitly make the extension members `@objc` in order to suppress that error, since Swift 4 no longer infers it.

@swift-ci
Copy link
Collaborator Author

swift-ci commented Sep 4, 2017

Comment by Ayush Goel (JIRA)

FWIW, it happens in Xcode 8.3.3. Hope Swift 4 resolves the matter. I face it when extending NSFetchedResultsController.

@swift-ci
Copy link
Collaborator Author

swift-ci commented Apr 6, 2018

Comment by Daisy Ramos (JIRA)

+1 seeing the same error, when extending RACSignal from ReactiveObjC framework

Extension of a generic Objective-C class cannot access the class's generic parameters at runtime

in Swift 4.1 Xcode 9.3

@swift-ci
Copy link
Collaborator Author

swift-ci commented Jun 7, 2019

Comment by Amol Y Patil (JIRA)

Currently, I am using swift 4.2 and Xcode 10.1.

I have recently updated libraries as below :

Using ReactiveCocoa (9.0.0)

Using ReactiveObjC (3.1.1)

Using ReactiveSwift (5.0.1)

Using Result (4.1.0)

and I am getting the same error :

Extension of a generic Objective-C class cannot access the class's generic parameters at runtime

my func looks like :

extension RACSignal {

**public func toSignalProducer(parameters) -\> SignalProducer\<AnyObject?, NSError\> {**

**}**

}

@swift-ci
Copy link
Collaborator Author

Comment by Amol Y Patil (JIRA)

Hi Daisy,

Did you find solution for this compiler error ?
Actually, I am facing same issue while updating Reactive libraries. Spend lot of time but could not find solution on how to fix this issue.

Thanks,
Amol.

@swift-ci
Copy link
Collaborator Author

Comment by Charlton Provatas (JIRA)

Hitting this one as well �

@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

3 participants