The following worked in previous versions of Xcode, but fails to compile on the Xcode 11.4 beta.
protocol BaseProtocol { }
protocol SubProtocol: BaseProtocol { }
class FooClass {
func makeViewController<U: BaseProtocol>(u: U) { fatalError() }
}
class FooSubClass: FooClass {
override func makeViewController<U: SubProtocol>(u: U) { // Error here. Text below.
fatalError()
}
}
/*
Overridden method 'makeViewController' has generic signature <U where U : SubProtocol> which is
incompatible with base method's generic signature <U where U : BaseProtocol>; expected generic
signature to be <U where U : BaseProtocol>
*/
Is this a regression or expected behaviour. If it's expected, is there a workaround?
There's some existing discussion about this change in this thread. It's intentional and the old behavior shouldn't have been allowed, because the override needs to accept all possible inputs that the base method does, which means it can't constraint the type further.
let base: BaseProtocol = ...
let subFoo = FooSubClass(...)
(subFoo as FooClass).makeViewController(u: base)
Note that a SubFooClass instance is aFooClass. Therefore, it must be able to accept all kinds of input that the FooClass will. What should happen in your example? Should the superclass implementation be silently invoked when there is only a partial override in the subclass?
I think that would be too magical.
This current behaviour was a bug. It has been fixed.
If we want to consciously allow partial overrides, I think we should fix that as a separate feature, perhaps with a partial override keyword, and clear and well-documented semantics for behaviour. I'm not sure we even want that.
Probably it's better to model your FooClass as a protocol with associated type requirements, and implement your SubFooClass as an implementation with a specific constraint on the associated type.