Inherit an associatedtype to parent protocol

I tried to inherit an associatedtype to parent protocol. But can't make it work.

Is it a way to do that?

enum UntypedResult<E: Swift.Error> {
    case success, failure(E)
}

protocol InterchangableError<Err> {
    associatedtype Err: Error
    var toUntypedResult: UntypedResult<Err> { get }
    var toOptionalError: Err? { get }
}

// Error, can't inherit Failure to InterchangableError
protocol InterchangableResult<Success, Failure>: InterchangableError<Failure> { 
    associatedtype Success
}

Hi @carlhung,

In protocol declarations such as InterchangeableError<Err>, the Err type is known as a primary associated type. It's not the same thing as the generic parameter E in UntypedResult<E>, although (as you can probably guess from the commonality in spelling) there are certain parallels which Swift wants to emphasize. However, Err is still just an associated type.

A helpful rule of thumb is that your protocol definitions should compile perfectly if everything between the angle brackets <...> were deleted entirely, so there are a few things to fix:

First, primary associated types must always be restated as an ordinary associated type among the protocol's requirements. So right off the bat, you know there's one thing missing in your declaration of InterchangeableResult: you must have associatedtype Failure somewhere.

Second, when a protocol refines (sometimes also referred to as "inherits") another protocol, one does not use the <...> notation to constrain primary associated types because there aren't multiple distinct protocols to refine depending on what's in the angle brackets. When you have a generic class Foo<T>, Foo<Int> and Foo<String> are two distinct types, but when you have a protocol Bar<U>, you only have a single protocol Bar with Bar<Int> and Bar<String> just specifying the associated type U.

Instead, you can constrain Failure to be the same as Error in the declaration in the usual manner for associated types:

protocol InterchangeableResult<
  Success, Failure
>: InterchangeableError where Failure == Err { 
    associatedtype Success
    associatedtype Failure
}