Did you test in on a beta version? Conditional conformances don't work at all for me since I have the regular Xcode (Swift 4.0.3). Maybe the author of this topic is under 4.2 as well?
SR-6474 notwithstanding, I don't think this is a bug, although the error message certainly seems off-base.
Take a look at the implied conditional conformance section in the conditional conformance design doc, which is cited in SR-6474. It requires the "implied" conformances to be stated explicitly to forestall ambiguity of implementation. This topic is also being discussed in more detail in this thread.
It looks like Breathable and Movable don't actually need separate extensions. You can just name them in the same extension as for Leavable.
The code in the OP is missing an implementation of move() for Bee, so in fact it is not Leavable as shown. But I don't think the compiler ever got to that point.
But if it's not a bug, then it is a bug that it is possible (in recent versions of the compiler) to conditionally conform eg Array and Optional to Fooable (in my example program above).
That bug report also says that explicitly mentioning the implied protocols doesn't always work. However, the sample code there seems to work fine for me in 9.3 beta 4, so perhaps that part is already fixed.
It sounds like there may be a couple of different bugs in play as well as the underlying design issue of how to handle implied conformances. But the upshot for the OP is that I don't think it's supposed to work to just extend directly to Leavable.
Yes, so for completeness, here's how to conditionally conform MyArrayOfOne to Foobarable (leaving Array and Optional there to demonstrate -- what turned out to probably be -- the actual bug):
protocol Fooable {
func foo()
}
protocol Barable {
func bar()
}
protocol Foobarable : Fooable, Barable {
}
// Conditionally conforming Array to Foobarable works by just doing this:
extension Array: Foobarable where Element: Foobarable {
func foo() { forEach { $0.foo() } }
func bar() { forEach { $0.bar() } }
}
// Even though it probably shouldn't. The same goes for eg Optional:
extension Optional: Foobarable where Wrapped: Foobarable {
func foo() { self?.foo() }
func bar() { self?.bar() }
}
// But, as discussed above, in order to conditionally conform eg this:
struct MyArrayOfOne<Element> {
let element: Element
}
// You have state each conformance explicitly:
extension MyArrayOfOne: Fooable where Element: Fooable {
func foo() { element.foo() }
}
extension MyArrayOfOne: Barable where Element: Barable {
func bar() { element.bar() }
}
extension MyArrayOfOne: Foobarable where Element: Foobarable {
}
// This compiles with default toolchain of Xcode 9.3 beta 4.
Yes, the extra ones are uninformative here and the compiler could allow you not to declare them explicitly. But that wouldn't work in all cases.
Near as I can tell, the heart of the issue is that you may not have more than one extension that conforms a type to a particular protocol. Otherwise it's ambiguous which versions of the protocol methods should be called when you invoke protocol methods on that type.
The "no implicit conformances" rule prevents you from inheriting multiple implementations of an "upstream" protocol by requiring all intermediate conformances to be explicitly declared. If they are found to duplicate existing conformances, the compiler can flag them at the point of declaration.