SE-0516: Borrowing Sequence

I feel like this is a miss for a few reasons:

  • It's a really clunky protocol; it'd be a shame for this to be "the way to write sequences". Sequence is pretty easy. Rust's Iterator is easier in most circumstances. This is worse.
  • It seems to be "too soon" — it doesn't handle nonescaping elements, and doesn't seem like it'll be extensible to nonescaping elements in the future, given that they require lifetime annotations. I don't think nonescaping elements are an edge-case or uncommon need. So won't we just be back here in 6-12 months when lifetimes have caught up, trying to specify BorrowingNonescapingSequence?
  • It seems to be "too soon" — implementing it requires using the Lifetimes experimental feature. This was promised to be stable, but broke source-compatibility between 6.2 and 6.3 already. I don't trust that implementations of BorrowingSequence made for 6.4 will compile in 6.5.
  • I don't like that this isn't "replacing" Sequence, since there are cases that Sequence supports but BorrowingSequence does not. I'd like to see more discussion of whether there is a design that allows for a true one-size-fits-all?

Thoughts about a more one-size-fits-all solution:

Are we just ignoring Rust's prior art here? In Rust:

  • Iterator can be over values or borrows, and might or might not itself be escaping depending on which one.
  • There's only standardization on how to get a consuming iterator from a container. This means that for loops can be less ergonomic (for item in container consumes the container, for item in container.iter() is an ad-hoc standard to get a borrowing iterator, but it allows for other options like for item in container.drain(3..14) to get an iterator that consumes items in a specified range of a Vec, for example.

So what if,

  • We adjust IteratorProtocol to allow nonescaping implementors & nonescaping Element
  • The compiler's for syntax gets special support for IteratorProtocol<T> (current), IteratorProtocol<Borrow<T>> (new) and IteratorProtocol<Span<T>> (new):
    • When iterating sequences of Borrow, the iteration variable is implicitly shorthand for borrow.value (so you don't have to manually deref the borrow on each use within the loop)
    • When iterating sequences of Span, the iteration variable is implicitly shorthand for span[i]. This is more or less equivalent to BorrowingIteratorProtocol from the current proposal.
  • Sequence remains shorthand for "i can get a copying, escapable iterator"
  • We create an ad-hoc standard for getting a borrowing iterator, eg. for element in container.borrow(). I suggest this because it avoids ambiguity over "which kind of iterator is this for loop using" compared to having both Sequence and BorrowingSequence, and also makes it clear that offering other kinds of iterator through other ad-hoc methods is reasonable (see drain)
19 Likes