Skip to content

[SR-1176] Using protocols (inheriting from class) as generic parameter which needs to be of type AnyObject fails #43784

@ffried

Description

@ffried
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
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.compilerThe Swift compiler itself

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions