Now, I want to keep as much of the functionality of Vec as possible, but ensure that push/pop is impossible. Is there a known idiomatic solution to this problem?
Most of Vec's functionality is available because it dereferences to a slice. If your type does the same, then you'll be able to call all of the slice methods, which include accessing and modifying elements but not changing size:
This is brilliant. Expanding on your chain of logic, a vec that we can only modify but not change size is basically a &'a mut [T]. So we are tempted to write:
FixedSizeVec<'a, T>(&'a mut [T]);
but then to avoid lifetimes, we would have to make it
FixedSizeVec<T>(Vec<T>);
and have it return a &'a mut [T] instead. This makes sense now. Thanks!