为什么这个通用的基于协议的框架不能编译?

Why won't this generic protocol-based framework compile?

下面是我在 Xcode 9 Beta 5 中开发的 Swift 4 框架的 SSCCE:

// MARK: - Protocols

public protocol BaseFoo {
    associatedtype FooBar: Bar
}



public protocol Bar {
    associatedtype BarData: DataHolder
}
public extension Bar {
    public typealias Callback = BarCallback<BarData>
}



public typealias BarCallback<Result: DataHolder> = (Result?, Error?) -> Void



public protocol DataHolder {
}



// MARK: - Implementations

public class MyFoo: BaseFoo { // Does not compile
    public typealias FooBar = MyBar
}



public protocol MyBar: Bar where BarData: MyDataHolder {
}
public protocol MyDataHolder: DataHolder {
}

但是编译器抱怨“Type 'MyFoo' does not conform to protocol 'BaseFoo'”。 Xcode 询问 "Do you want to add protocol stubs?",当我单击 "Fix" 时,它会这样做:

public class MyFoo: BaseFoo {
    public typealias FooBar = <#type#>

    public typealias FooBar = MyBar
}

这似乎表明 MyBar 不是满足 FooBar 的正确类型,但它显然是一个 DataHolder,正如所要求的那样。 这是怎么回事,我该如何解决?

当我尝试使用 Swift 3 进行编译时,我对此有了一些了解,这只需要很少的更改。现在,我收到两个错误:

public class MyFoo: BaseFoo { // Type 'MyFoo' does not conform to protocol 'BaseFoo'
    public typealias FooBar = MyBar // Protocol 'MyBar' can only be used as a generic constraint because it has Self or associated type requirements
}

啊哈!现在这是我习惯处理的错误。所以,我把它作为通用参数放在 class 声明中:

public class MyFoo<_MyBar: MyBar>: BaseFoo {
    public typealias FooBar = _MyBar
}

现在它编译得很好!将该修复程序带回 Swift 4 会得到相同的结果;现在它编译得很好。

所以问题是MyBar过于泛化,不能直接作为类型使用,需要通过泛型参数进行抽象。