devios1
devios1

Reputation: 38025

Swift 3 Collection subclass won't compile

I have a Node class in Swift that implements Collection so that each Node acts recursively as a collection of child nodes of the same type.

The problem is when I subclass Node, I still want the subclass to act as a collection of Nodes, but Swift won't even compile when I try to iterate over an instance of the subclass DerivedNode, complaining that:

IndexingIterator<Node> is not convertible to IndexingIterator<DerivedNode>.

I'm confused why it would be trying to do this. I don't care about iterating over DerivedNodes, they should continue to be iterated as Nodes.

Interestingly, the compiler/editor knows they should be of type Node as the help popup shows the right type. But it still fails to compile for some reason.

enter image description here

Here's how I implemented the Collection protocol:

extension Node: Collection {
    public typealias Index = Int

    public var startIndex: Int {
        return 0
    }

    public var endIndex: Int {
        return attributes.count
    }

    public func index(after i: Int) -> Int {
        return i + 1
    }

    public subscript(i: Int) -> Node {
        return attributes[i].value
    }
}

Upvotes: 0

Views: 96

Answers (1)

Rob Napier
Rob Napier

Reputation: 299495

If you do not declare an iterator, then Collection gives you one:

public func makeIterator() -> IndexingIterator<Self>

You don't want that one, though. You want IndexingIterator<Node>. So you need to provide your own makeIterator() method:

public func makeIterator() -> IndexingIterator<Node> {
    return IndexingIterator(_elements: self)
}

This requires calling an undocumented initializer for IndexingIterator. IMO that's a bug in the stdlib. Creating an IndexingIterator by hand should be supported.

Upvotes: 1

Related Questions