Uploaded image for project: 'Swift'
  1. Swift
  2. SR-1176

Using protocols (inheriting from class) as generic parameter which needs to be of type AnyObject fails

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Medium
    • Resolution: Done
    • Component/s: Compiler
    • Labels:
      None
    • Environment:

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

      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
      }
      

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              Unassigned Unassigned
              Reporter:
              ffried Florian Friedrich
              Votes:
              6 Vote for this issue
              Watchers:
              9 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: