// Code from https://github.com/cx-org/CombineX/blob/CXNamespace/Sources/CXNamespace/CXNamespace.swift
public protocol CXWrapper {
associatedtype Base
var base: Base { get }
init(_ base: Base)
}
public protocol CXWrappable {
associatedtype CX: CXWrapper where CX.Base == Self
var cx: CX { get }
}
public extension CXWrappable {
var cx: CX {
return CX(self)
}
}
// Note CX == Self is inferred here. Adding this requirement produce a warning.
public protocol CXSelfWrapping: CXWrappable, CXWrapper where Base == Self /* CX == Self */ {}
public extension CXSelfWrapping {
var base: Base {
return self
}
init(_ base: Base) {
self = base
}
}
AFAICS CXSelfWrapping don't have any associated type, and all requirements have default implementation. Any type can conforms to CXSelfWrapping for free. However no type can conform to it.
// Type 'A' does not conform to protocol 'CXSelfWrapping'
// Do you want to add protocol stubs?
class A: CXSelfWrapping {}
// Type 'Optional<Wrapped>' does not conform to protocol 'CXSelfWrapping'
// Do you want to add protocol stubs?
extension Optional: CXSelfWrapping {}
// Type 'Optional<Wrapped>' does not conform to protocol 'CXWrappable'
// Type 'Optional<Wrapped>' does not conform to protocol 'CXWrapper'
extension Optional: CXSelfWrapping {
public typealias CX = Optional<Wrapped>
}
Is this a bug or intended behavior, Am I doing wrong?
Let us remove all the noise and boil this down a bit first:
protocol CXWrapper {
associatedtype Base
}
protocol CXWrappable {
associatedtype CX: CXWrapper where CX.Base == Self
}
protocol CXSelfWrapping: CXWrappable, CXWrapper where Base == Self {}
Hopefully it becomes easier to notice that you cannot conform to CXSelfWrapping for free: Base is constrained and determined but there's nothing stopping CX from being an arbitrary type like Foo:
class Foo: CXWrapper {
typealias Base = A
}
// Self == A
class A: CXSelfWrapping { // OK
typealias CX = Foo // : CXWrapper where CX.Base == Self
typealias Base = A
}
That warning you mentioned is actually a bug, filed it under SR-11670.
Thank you. So CX == Self is necessary but the compiler ignored it and produce a warning?
In short, the CX == Self constraint is totally legal.
What happens is CX == Self internally yields a derived and redundant constraint Self: XSWrapper (because CX: CXWrapper), and the compiler erroneously emits a warning telling you the derived constraint is redundant, when only those explicitly written by the user should be allowed to be diagnosed as redundant.
P.S. Note that CX == Self will still not make the conformance "free", seems like we don't handle the == Self case yet :-(
^
SR-11671
2 Likes