I'm really confused by this behavior. I assume that this code should compile, but the compiler won't let me. It feels like a bug because the inherited protocol does not gets satisfied nor it's automatically conditionally conformed.
public struct Generic<Constraint> {}
public protocol ConversionValueLookup {
associatedtype ConversionValue
}
public protocol SomeProto {}
public protocol ConvertibleA : ConversionValueLookup where ConversionValue : SomeProto {}
public protocol ConvertibleB : ConversionValueLookup where ConversionValue : SomeProto {}
/*
error: type 'Generic<Constraint>' does not conform to protocol 'ConversionValueLookup'
extension Generic : ConvertibleA where Constraint : ConvertibleB {
^
note: type 'Generic<Constraint>' does not conform to inherited protocol 'ConversionValueLookup'
public protocol ConvertibleA : ConversionValueLookup where ConversionValue : SomeProto {}
*/
extension Generic : ConvertibleA where Constraint : ConvertibleB {
public typealias ConversionValue = Constraint.ConversionValue
}
// Uncomment the next line to fix the error
// extension Generic : ConversionValueLookup where Constraint : ConvertibleB {}
Is it a bug, is it a rule I don't understand or something else?
The types do not have a lot of semantics in the example, because the example contains the bare bones to reproduce the issue. In the real codebase protocol that is named ConvertibleA
has more additional constraints and semantics and it's applied to a set of *Container
types, while ConvertibleB
is similar constrained, yet slightly different is applied on *Constraint
types. I use this tactics to extract and forward types stored in the generic parameter lists of nested generic types to enclosing parent generic types. This allows me to build a strongly constrained and statically safe API.