It's because the constraint you add in the associatedtype declaration is just a constraint, and doesn't actually resolve the type.
To be able to resolve the associatedtype you need some kind of reference in the protocol (or the implementation) to that associatedtype.
In your example, your implementation only "resolve" the Iterator associatedtype:
public protocol MySequence {
func makeIterator() -> Self.Iterator
}
class MultiSet<T: Hashable> : Swift.Sequence {
func makeIterator() -> Array<T>.Iterator {
return data.makeIterator()
}
}
Because you "replaced" Iterator with Array<T>.Iterator in the implementation, Swift understands how Iterator should be resolved. But At that point Element is still not resolved.
Note: Xcode does ask for both Element and Iterator type aliases in the implementation, but Element is the only one actually missing.
If you add
typealias Element = T
In MultiSet it fixes the error.
If you want Swift to be able to resolve Element you will need the same kind of "reference", either in your implementation of MultiSet or directly inside your protocol with an extension.
For example:
public protocol MySequence {
associatedtype Element where Self.Element == Self.Iterator.Element
associatedtype Iterator : IteratorProtocol
func makeIterator() -> Iterator
func foobar() -> Element? // added a reference to Element
}
extension MySequence {
func foobar() -> Iterator.Element? {
nil
}
}
struct MultiSet<T>: MySequence {
var data = [T]()
func makeIterator() -> Array<T>.Iterator {
return data.makeIterator()
}
}
This will allow Swift to resolve Element to Iterator.Element.
Note: You can define foobar inside MultiSet without a default implementation in an extension. I used this example because it is how it's done inside Sequence.
If you take a look at the Sequence implementation (Source code) you will notice the _customContainsEquatableElement function (that references Element), with a default implementation (which resolve Element to Iterator.Element)
public protocol Sequence {
func _customContainsEquatableElement(
_ element: Element
) -> Bool?
}
// [...]
extension Sequence {
public func _customContainsEquatableElement(
_ element: Iterator.Element
) -> Bool? {
return nil
}
}
This is why when implementing Sequence you don't have to explicitly resolve Element, it's implicitly resolved to Iterator.Element.