So we can ignore String here since it’s basically a wrapper around Vec. There are logically 3 kinds of Vec that we’re concerned with here:
- Vec always on Heap
- Vec always on Stack
- Vec adaptively on Stack or Heap
You are proposing the third option be used unconditionally, I believe. But this would cause lost performance when Vecs really want to be pure stack (because they are known apriori to be small) or pure heap (because they are know apriori to be big, or need to be moved around a lot). Every access would have to branch on what “mode” the Vec is in.
I instead propose that we have 3 distinct types: HeapVec<T>, StackVec<T, n>, and HybridVec<T, n>. These can all three in turn be implemented on top of a AbstractVec<T, Buf> where Buf is a trait that abstracts over managing and accessing the buffer (ptr(), cap(), and reservation methods) with three implementers:
HeapBuf<T>
StackBuf<T, n>
HybridBuf<T, n>
struct AbstractVec<T, Buf> {
len: usize,
buf: Buf,
}
struct HeapBuf<T> {
ptr: *mut T,
cap: usize,
}
struct StackBuf<T, n> {
elems: [T; n],
}
struct HybridBuf<T, n> {
buf: Either<HeapBuf<T>, StackBuf<T, n>>,
}
We are however missing the type-system tooling necessary to implement StackBuf<T, n>, and when we will get them is unclear.
In the future it should be easy enough to make Vec<T> an alias for HeapVec<T> (what it is now), HybridVec<T, 7> or anything else we think is ideal.