[Pitch #2] Safe Access to Contiguous Storage

Good points!

My beef with the name validateBounds is that (1) despite its promise, it is actually validating an index, not the bounds, and (2) it is a predicate, but it doesn't read like one. The latter issue also applies to UTF8Span.boundsCheck.

FWIW, in swift-collections, I have recently found a need to introduce similar functionality, and I ended up calling the predicate isValid(_: Index). This would not work directly for Spans, as they use Int as their index -- but isValidIndex(_: Int) might be an option to consider. The sibling method for validating a range of indices may perhaps be called isValidSubrange(_: Range<Int>), as that is the term we've established for such ranges.

Note: defining these APIs would set a clear pattern for other types to emulate, but it would probably not be a good idea to make them general requirements of any protocol. Index validation is tricky to do efficiently; it is generally best to do it as an integral part of actual accesses, not as a standalone operation. Very often, the outcome of index validation is not just a yes/no result, but also some direct reference to a part of the underlying container representation that can be directly used to access the addressed item -- a pure isValidIndex predicate would discard all this work, only to redo it from scratch when the validated index actually gets used.

(Alternatively, we can of course choose not to provide these members at all -- the swift-collections case wasn't simply about avoiding having to spell out a trivial range check.)

I'd personally prefer to avoid spending API surface on variants that simply assert on the validity of an index -- it raises too many complications:

  • Is the client happy to use precondition or would they prefer assert?
  • Inability to customize the runtime error message that the function emits on failure.
  • Having to pollute the API signature with #file/#line arguments.

It seems okay to me to let clients invoke precondition themselves if that is what they want to do. The swift-collection example also defines func validate(_: Index), and it suggests validateIndex/validateSubrange for naming. But I regret adding Rope.validate; I think it would work better as an internal helper rather than public API. (Luckily, the module that defines it isn't source stable yet.)

4 Likes