"Type 'any B' cannot conform to 'A'" when B is actually a protocol that is derived from protocol A

I am trying to create a generic structure in my project and I am facing an issue where I get the error "Type 'any B' cannot conform to 'A'", where protocol B is derived from protocol A.

I don't understand why such a structure is problematic and I would really appreciate any insight or alternative solution for this issue I am having.

Issue:

I have a general base protocol-class pair like the following.

protocol A { }

class AClass<T: A> { }
  • To give an example of my use case, protocol A can be PresenterLogic where AClass is BaseInteractor.

I have a second protocol-class pair which I want to specialize according to its use case.

protocol B: A { }

class BClass: AClass<B> { } // Here, I get "Type 'any B' cannot conform to 'A'"
  • For example, protocol B being MyPresenterLogic and class BClass being MyInteractor.

Specific Use-Case:

To give a more specific use case, I am trying to build a VIP structure such as the following.

// Base VIP (Ex: Interactor)

protocol PresenterLogic { 

}

class Interactor<PL: PresenterLogic>, BusinessLogic { 
  var presenter: PL?
}

// VIP for Specific Screen (Ex: Interactor)

protocol MyPresenterLogic: PresenterLogic { 

}

class MyInteractor: Interactor<MyPresenterLogic> { 
  // I don't want to declare a second `myPresenter: MyPresenterLogic` here
}

I don't want to declare another presenter instance in MyInteractor, (such as myPresenter: MyPresenterLogic. I want to be able to use the same presenter instance to be inferred to have the sub-protocol type.

That is why I want to use generic classes, but I am stuck. I am searching if this is supported. Any insight is appreciated. Thank you.

Answered by DTS Engineer in 784989022

The error message is correct. Your code:

protocol B: A { }
class BClass: AClass<B> { }

by definition means:

protocol B: A { }
class BClass: AClass<any B> { }

That says that BClass is a subclass of a specialization of AClass<T> where T is the existential type any B. However, your definition of A is:

protocol A { }
class AClass<T: A> { }

This by definition means that T is a concrete type that conforms to A. any B is an existential type, not.a concrete type, so it's can't work for classA.

To get around this, you can do this:

protocol B: A { }
class BClass<U: B>: AClass<U> { }

In other words, make BClass also generic, taking a concrete type U that conforms to B and hence conforms to A.

However, if you need BClass to really be specialized on any B, you'll have to do something to AClass to let it take an existential type as a parameter.

Accepted Answer

The error message is correct. Your code:

protocol B: A { }
class BClass: AClass<B> { }

by definition means:

protocol B: A { }
class BClass: AClass<any B> { }

That says that BClass is a subclass of a specialization of AClass<T> where T is the existential type any B. However, your definition of A is:

protocol A { }
class AClass<T: A> { }

This by definition means that T is a concrete type that conforms to A. any B is an existential type, not.a concrete type, so it's can't work for classA.

To get around this, you can do this:

protocol B: A { }
class BClass<U: B>: AClass<U> { }

In other words, make BClass also generic, taking a concrete type U that conforms to B and hence conforms to A.

However, if you need BClass to really be specialized on any B, you'll have to do something to AClass to let it take an existential type as a parameter.

"Type 'any B' cannot conform to 'A'" when B is actually a protocol that is derived from protocol A
 
 
Q