I'm trying to write a protocol that conforms to the Collection Protocol, and it has an associatedType - Object and a property object.
protocol DDCDataSource: Collection
{
associatedtype Object
var object: Object {get set}
}
I want to add some default functionality for the case where Object also conforms to the Collection protocol, namely just directly return Object's implementation of these required Collection properties and functions. It seems like it all works except for Collection's requirement for a subscript.
Cannot subscript a value of type 'Self.Object' with an index of type 'Self.Object.Index'
extension DDCDataSource where Object: Collection
{
typealias Index = Object.Index
var startIndex: Object.Index {
get {
return object.startIndex
}
}
var endIndex: Object.Index {
get {
return object.endIndex
}
}
subscript(position: Object.Index) -> Element
{
return object[position]
}
func index(after i: Object.Index) -> Object.Index {
return object.index(after: i)
}
}
Short answer: Change the return type of the subscript method to
Object.Element
or add a type alias (in a similar way as you did for the
Index
type)That makes the code compile and run as expected.
Explanation: The
subscript
method ofCollection
is declared aswhere
Self.Index
andSelf.Element
are associated types of `Collection. With your codethe compiler infers
Self.Index
to beObject.Index
, but there is no relation betweenSelf.Element
andObject.Element
(which is returned byobject[position]
). The error becomes more apparent if you add an explicit cast:Now the compiler complains
The correct solution is not the forced cast but to make the compiler know that
Self.Element
isObject.Element
, by adding a type alias or by changing the return typeso that the compiler infers
DDCDataSource.Element
to beObject.Element
.Full self-contained example: (Swift 4, Xcode 9 beta 6)
(Note that you can omit the
get
keyword for read-only computed properties.)