badassoc2.swift:14:8: error: type 'S' does not conform to protocol 'P2'
struct S: P2 {
^
badassoc2.swift:15:8: note: candidate has non-matching type '(String) -> ()'
func req2(_ input: String) { print(input) }
^
badassoc2.swift:14:8: error: type 'S' does not conform to protocol 'P1'
struct S: P2 {
^
badassoc2.swift:7:8: note: protocol requires function 'req2' with type '(S.Input) -> ()'; do you want to add a stub?
func req2(_ input: Input)
^
badassoc2.swift:2:18: note: protocol requires nested type 'Input'; do you want to add it?
associatedtype Input
^
It seems like the compiler should be able to figure out the type of Input without any extra help from me. Is this a compiler bug? Or something that I should not expect the compiler to be able to do for me?
I have discovered that I can fix it by adding the line associatedtype Input to protocol P2.
I believe this is a known shortcoming, and it affects the standard library as well. The solution employed there is the same one you found, namely adding the associatedtype to the refining protocol.
public protocol BidirectionalCollection: Collection
where SubSequence: BidirectionalCollection, Indices: BidirectionalCollection {
// FIXME: Only needed for associated type inference.
override associatedtype Element
override associatedtype Index
override associatedtype SubSequence
override associatedtype Indices
⋮
}
Is there any scenario in which we don’t want this behavior? As in, could we just tell the compiler to, essentially, automatically insert override associatedtype XYZ for every associated type of the parent protocol? Are there any drawbacks to doing so?
Associated type inference is intentionally limited to a single level for performance reasons. The associated type inference engine was notorious for how unstable and bogus it could be. Not because of quality of implementation – improving the performance of type inference is itself a very complex problem fundamentally.