Hi, I’m a bit stuck, please can anyone point me in the right direction?
We have this init definition: init<T: StackContainable>(childViewController: T) where T: UIViewController {
So T must conform to StackContainable and be a UIViewController. So far so good.
If I have a class ThisWorksViewController: UIViewController, StackContainable, this can be passed straight in.
However, what I need is to have an array of StackContainableUIViewControllers that can each be passed to the init, so I need to do something like:
let viewControllers: [UIViewController & StackContainable] - i.e. an array of ViewControllers with StackContainable conformance. But for some reason that's eluding me, an element from this array (UIViewController & StackContainable) cannot be passed into that init function, even though it would conform to the generic requirements.
I get this error message:
Cannot invoke initializer for type '...' with an argument list of type '(childViewController: UIViewController & StackContainable)'
I thought protocol composition using & was exactly what was needed here - can anyone shed any light?
Protocols or existentials do not conform to themselves. When you pass an array element of type A & B to a function expecting a type that conforms to A & B, you're basically asking for the opposite.
class A {}
protocol P {}
class AP: A, P {}
let array: [A & P] = []
func foo<T: A & P>(_ arg: T) {}
foo(AP()) // OK, AP conforms to P and is a subclass of A
foo(array[0]) // A & P - the type of the array element - does not conform to A & P
Generics are often not necessary when working with existentials unless you're bothering about associated types. Using the type directly lets you pass both instances of a conforming type and instances that are dynamically stored as UIViewController & StackContainable.
The error message really has to be improved though. It's not a big deal to conditionalize the diagnostic based on T == inferred type, but it should be Argument type 'A & B' does not conform to expected type 'A & B' without it.
I'll file a bug anytime soon.