Question about covariance with instance variablesk

I'm a bit confused why the following doesn't compile:

import UIKit
import Foundation

protocol Foo {}
protocol Bar {}
class Test: UIViewController & Foo & Bar {}

protocol Qux {
    var test: UIViewController & Foo & Bar { get }
}

class Zag: Qux {  // compiler error! Protocol requires property `test`
                            // with type `UIViewController & Bar & Foo` 
    var test: Test    // Candidate has non-matching type `Test`
    init(test: Test) {
        self.test = test
    }
}

Meanwhile the compiler is perfectly happy if we do this:

class Zag: Qux { 
    var test: Test
    init(test: Test) {
        self.test = test
    }
}

func doSomething(with thing: UIViewController & Foo & Bar) {
    print("something")
}

let mytest = Test()
let zag = Zag(test: mytest)

doSomething(with: zag.test)

It does not seem that class Zag can conform to Qux on the basis of test: Test even though below we see that class Test meets all the requirements: UIViewController & Foo & Bar.

Meanwhile in the case of func do(with:), it seems that covariance holds for an instance of Test being used as a UIViewController & Foo & Bar, without explicit casting or generics.

Just curious what the rationale for this might be, or if this is an area in which Swift is planned to have future support but currently it doesn't. Thanks

PS—I'd note that, counterintuitively, the following does compile:

class Zag: Qux {
    var test: Test
    init(test: Test) {
        self.test = test
    }
}

extension Qux where Self: Zag {
    var test: UIViewController & Foo & Bar {
        self.test as UIViewController & Foo & Bar
    }
}

This makes me think that there was probably a decision made to not auto-synthesize this kind of extension for covariance, so I'm curious the reasons.

Terms of Service

Privacy Policy

Cookie Policy