import UIKit
protocol A {
func f()
}
protocol B {
var v: A? { get set }
}
class C: B { // Type 'C' does not conform to protocol 'B'
var v: UIViewController? = nil
init(v: UIViewController?) {
self.v = v
}
}
// Option A:
extension UIViewController: A {
func f() {
print("lol")
}
}
// Option B:
extension A where Self: UIViewController {
func f() {
print("lol")
}
}
So basically the compiler should have all the info it needs to assert that UIViewController indeed conforms to A and thus is safe to be put as the type of v in class C... But for some reason it just doesn't.
And I know using an associated type works here, but I really can't since it renders my protocol completely unusable for my use case (because of "can only be used as a generic constraint").
So is there anything I can do to fix this or do I have to resort to making v's type AnyObject and casting it like I would in Obj-C?
Thanks!
zoul
(Tomáš Znamenáček)
2
This isn’t safe, is it? If the code compiled, someone could type-erase C to B, set v to some A other than a UIViewController and then you would be in trouble once C would try to use v as a view controller.
2 Likes
Hi Tomáš,
Thanks for the response! Could you write a small example that would violate the type system (using type erasure) if my code would, hypothetically, compile? Because I'm not sure I quite get what you mean.
Thanks!
zoul
(Tomáš Znamenáček)
4
In code:
extension String: A {
func f() {}
}
var c: B = C(v: UIViewController())
c.v = "boom"
This would be valid if your code compiled. And now if c tried to use v as a view controller, it would be in for a surprise. The key point is that anyone adopting B promises to work with any A, while C only works with As that are also view controllers.
1 Like