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-1176] Using protocols (inheriting from class) as generic parameter which needs to be of type AnyObject fails #43784

Closed
ffried opened this issue Apr 7, 2016 · 9 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself

Comments

@ffried
Copy link
Contributor

ffried commented Apr 7, 2016

Previous ID SR-1176
Radar rdar://24975479
Original Reporter @ffried
Type Bug
Status Resolved
Resolution Done

Attachment: Download

Environment

Xcode Version 7.3 (7D175)
OS X Version 10.11.4 (15E65)

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

md5: 10b769def9e1e1f271c406d677bd5b09

duplicates:

  • SR-55 non-@objc protocol existentials do not conform to their own protocol type

Issue Description:

When using a generic struct (WeakContainer<T>) where the generic type needs to inherit from AnyObject, it can't be created by passing a protocol (declared by inheriting from class) for the generic type T, although no other object than one that inherits from AnyObject can implement said protocol.

Steps to Reproduce:

  1. Create a generic type (e.g. struct WeakContainer<T: AnyObject>) with a generic type that needs to inherit from AnyObject
  2. Create a protocol which inherits from class (e.g. MyDelegate: class).
  3. Try to declare a variable of the generic type passing the protocol as generic parameter (e.g. WeakContainer<MyDelegate>)

Expected Results:
It should work without any errors since the only objects which are able to implement the protocol (e.g. MyDelegate) are classes which also implement AnyObject.

Actual Results:
Instead Xcode shows an error stating that the protocol can't be used as a concrete type conforming to AnyObject. (e.g.: Using MyDelegate as concrete type conforming to protocol AnyObject is not supported)

Full source code (also attached as playground):

//: ## WeakContainer.swift

// Protocol for a container which stores objects weakly. Protocol is necessary to use it e.g. in SequenceType extensions.
public protocol WeakContainerType {
    associatedtype ObjectType: AnyObject
    weak var storedObject: ObjectType? { get }
}

// A concrete implementation of a WeakContainerType.
// Generic type T needs to be an AnyObject to conform to WeakContainerType's ObjectType
public struct WeakContainer<T: AnyObject>: WeakContainerType {
    public typealias ObjectType = T
    public private(set) weak var storedObject: ObjectType?
    
    public init(_ object: ObjectType) {
        storedObject = object
    }
}

//: ## MyImplementation.swift

// A delegate which needs to be implemented by a class (aka AnyObject).
protocol MyDelegate: class {
    init()
}

// A class that implemented MyDelegate correctly
class MyClass: MyDelegate {
    required init() {}
}

// An instance of MyClass
let myInstance = MyClass()
// Works fine, MyClass is an AnyObject
let weakInstance = WeakContainer(myInstance)

// Can't do that, although MyDelegate can only be implemented by classes (AnyObjects) and protocols cannot instantiated themselves.
let weakProtocolInstance: WeakContainer<MyDelegate> = WeakContainer(myInstance)
// So I also can't create an array of delegate objects.
var arrayOfContainers: [WeakContainer<MyDelegate>] = []

// Proof: A protocol can't be instantiated directly (even when it defines an initializer)
let delegateObject = MyDelegate()

// Proof: A struct cannot implement MyDelegate
struct MyStruct: MyDelegate {}

// Proof: Neither can an enum
enum MyEnum: MyDelegate {
    case Test, Test2
}
@swift-ci
Copy link
Collaborator

Comment by Peter Livesey (JIRA)

Why was this marked as a duplicate of SR-55? It seems like a different issue? It at least gives a different error message.

@slavapestov
Copy link
Member

It's the same underlying problem in the implementation.

@slavapestov
Copy link
Member

s/problem/limitation to be more precise...

@swift-ci
Copy link
Collaborator

Comment by Peter Livesey (JIRA)

Great. thanks for the fix

@ffried
Copy link
Contributor Author

ffried commented Jan 19, 2017

@slavapestov This was marked as "Done". However the other duplicates of SR-55 were resolved with "Duplicate". Was this intentional, or should the resolution for this issue also be "Duplicate"?

@slavapestov
Copy link
Member

Yeah it's a duplicate.

@swift-ci
Copy link
Collaborator

Comment by Łukasz (JIRA)

@slavapestov Is that fixed?

I'm facing the same problem right now in Xcode 9.1 beta 2, Swift version 4.0.1 (swiftlang-900.0.68 clang-900.0.38)

public protocol WeakContainerType {
    associatedtype ObjectType: AnyObject
    weak var storedObject: ObjectType? { get }
}

public struct WeakContainer<T: AnyObject>: WeakContainerType {
    public typealias ObjectType = T
    public private(set) weak var storedObject: ObjectType?
    
    public init(_ object: ObjectType) {
        storedObject = object
    }
}

protocol MyDelegate: class {
    func delegateMethod()
}

func test(myDelegate: MyDelegate) {
    let weakProtocolInstance = WeakContainer<MyDelegate>(myDelegate)
}
/*
error: AnyObjectProtocolPlayground.playground:14:32: error: cannot invoke initializer for type 'WeakContainer<MyDelegate>' with an argument list of type '(MyDelegate)'
    let weakProtocolInstance = WeakContainer<MyDelegate>(myDelegate)
                               ^
*/
 

@swift-ci
Copy link
Collaborator

Comment by Łukasz (JIRA)

I found more details related to this bug here https://bugs.swift.org/browse/SR-6039 probably

@slavapestov
Copy link
Member

Yes, this is a duplicate of SR-55.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
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