I was thinking about arena-based tree representations in Rust and how one thing you lose is that you can't do statically checked split_mut-style partitioning (i.e. a mut ref to a node can be split into mut refs to its child nodes) since the reference granularity is now at the whole arena level. But upon further reflection, that's not quite true. If the index ranges for sibling subtrees are disjoint, you can split_at_mut the slice itself to get subarenas (a slice + index offset).
When you deref a handle index within a subarena, you now have to do both a lower and upper bound check (previously only the upper bound check was needed):
if index >= subarena.offset && index - subarena.offset < subarena.slice.len() {
Some(&subarena.slice[index - subarena.offset])
} else {
None
}
Note that this works just fine with child-to-parent and sibling links, but if they are outside your subarena you will fail the bounds check and get None.
@pervognsen I mean, by the usual identity this is just wrapping_sub(index, subarena.offset) < subarena.slice.len() anyway
@rygorous Sure, I had a deleted reply about that but since the point wasn't really about optimization I left it out. Main point is just that you need to know the subarena offset.
@pervognsen IIRC, Swift does: they have a rule that for sub-collections, the set of keys/indices must be a subset of the parent's, which they follow for slices as well.
@glaebhoerl @pervognsen I’m not 100% sure this was the best choice, but it is at least defensible as not catastrophic.
@glaebhoerl @pervognsen right, the indices of a slice are the same as the indices those elements had in the parent collection (so if I slice an array to hold elements [2…], that slice has 2-based indexing).