First of all, “inserting” is not a valid operation on MutableCollection, so that could not happen in generic code without additional constraints.
Second, what would happen is, in order to increment the index, the IndirectIndices instance would access the collection (which has been mutated) through its reference, and ask the collection to form the next valid index after the current one. This should succeed, and the loop will continue over the valid indices of the collection.
Contrast that with the existing attractive nuisance:
If you are iterating over indices that retain the collection, and the loop inserts a value, then the collection’s copy-on-write triggers and now the loop is using indices from one collection (the original, pre-mutation instance) to index into another collection (the new, silently-created copy). This can fail badly.
Edit:
In fact, inserting or removing elements while looping over indices can be problematic even for collections where indices is trivial:
var a = [1, 2, 3]
for i in a.indices {
a.remove(at: i) // Fatal error: Index out of range
}
Obviously that particular loop is terrible for many reasons, but the point remains—if you do in fact need to perform nontrivial modifications to a collection, then looping over IndirectIndices will work as expected, with no extra copies and no crashes, whereas indices won’t.
The more I think about it, the less I see any use-case for indices in generic code at all. If you’re not mutating the collection, then you can just loop over its values. And if you are mutating, then you really ought to follow the documented recommendation and manually advance an index.
I just don’t see the purpose of indices, since the one thing it looks like it would be good at, is actually a pitfall.
Are there any important uses of indices in the standard library?