1

I have created the playground code below in order to illustrate a difficulty that I am having with my current project. Can anyone help me to understand the compiler error on the last line?

import Foundation

//******************************************************************************
//                            This Compiles
//******************************************************************************

protocol Protocol1 : AnyObject {
    var related: [Protocol2] { get set }
}

protocol Protocol2 : AnyObject {
    var related: [Protocol1] { get set }
}

class Class1 : Protocol1 {
    var related = [Protocol2]()
}

class Class2 : Protocol2 {
    var related = [Protocol1]()
}

let class1 = Class1()
let class2 = Class2()
class2.related.append(class1)


//******************************************************************************
//                            This Does Not Compile
//******************************************************************************

class Weak<T: AnyObject> {
    weak var reference : T?
    init (_ reference: T) {
        self.reference = reference
    }
}

protocol ProtocolA : AnyObject {
    var related: [Weak<ProtocolB>] { get set }
}

protocol ProtocolB : AnyObject {
    var related: [Weak<ProtocolA>] { get set }
}

class ClassA : ProtocolA {
    var related = [Weak<ProtocolB>]()
}

class ClassB : ProtocolB {
    var related = [Weak<ProtocolA>]()
}

let classA = ClassA()
let classB = ClassB()
classA.related.append(Weak(classB)) // <= Cannot convert value of type 'Weak<ClassB>' to expected argument type 'Weak<ProtocolB>'

[I am adding words to the bottom of this question in order for there to be enough words to make the stack overflow "correctness checker" happy. I really do think that there is nothing more that I can say to add clarity to my question. The compiler error says it all]

Hamish
  • 78,605
  • 19
  • 187
  • 280
Verticon
  • 2,419
  • 16
  • 34
  • [Protocols don't always conform to themselves](https://stackoverflow.com/a/43408193/2976878) – in this case you cannot satisfy `Weak`'s generic placeholder `T` with `ProtocolB` or `ProtocolA`, as neither are types that currently conform to `AnyObject`. Although I'm not fully sure why the compiler lets you say `Weak` in the first place... – Hamish Nov 22 '17 at 17:24
  • You can minimise the example down to just `protocol P : AnyObject {}; class C {}; let c = C

    ()` btw.

    – Hamish Nov 22 '17 at 17:25
  • @Hamish Your "minimizes to" example produces the error "'P' is not convertible to 'AnyObject'" which is different but seems related (and which I am also encountering in my actual project). I intend to study the "Protocols don't ..." post but in the meantime what is beginning to sink in is that a protocol which inherits AnyObject is not in fact an AnyObject. But, whatever actually gets used at runtime will be! Its darned confusing. Hopefully the post will help. – Verticon Nov 22 '17 at 18:22
  • It's a different error, but it's the same issue – you can reproduce that error in your example by explicitly stating the generic placeholder, e.g `classA.related.append(Weak(classB))`. And yeah, it's an annoying current restriction of the compiler, the Swift team are hoping to lift it at some point though. – Hamish Nov 22 '17 at 18:25
  • Possible duplicate of [Protocol doesn't conform to itself?](https://stackoverflow.com/questions/33112559/protocol-doesnt-conform-to-itself) – Hamish Nov 29 '17 at 22:07

0 Answers0