I’ve noticed that a large chunk of the use cases for dynamicly sized types boil down to forgetting some information about a more specialized generic type. An example from the standard library is slices and arrays. Here an array is a generic type with a type parameter and a const parameter:
type Array<T, const N: usize> = [T; N];
Slices represent what we get if we make the size parameter dynamic and stored in the pointer rather than the type. The idea is to create a language feature to express this pattern of type construction.
Currently I think the most appropriate syntax would be overloading the dyn
operator so that:
type [T] = dyn<const N: usize> [T; N];
Here dyn
moves the information required to recover the specific type over to the pointer. This is consistent with the current use of dyn
for trait objects. In trait objects the dyn
signifies moving the type implementing the trait from the type to the pointer in the form of a vtable. In my proposed syntax we get the equivalence:
dyn Trait = dyn<T: Trait> T
This syntax also create new type constructs, such as:
Box<dyn<T: Debug> (String, T)> //A box containing both a string and a trait object.
This generalization of the dyn
operator would allow libraries to only implement list extensions types for arrays and vecs, and to only implement things for the resulting slice type. In a linear algebra library, vectors and matrices could be defined as:
struct Vector<T, const N: usize>([T; N]);
struct Matrix<T, const N: usize, const M: usize>([[T; N]; M]);
Using these definitions, dyn<const N: usize> Vector<T, N>
would be a dynamicly sized vector, and dyn<const N: usize, const M: usize> Matrix<T, N, M>
would be a dynamicly sized matrix.
These new types could help rust’s story of !Sized
types via treating them as more specific types that we simply forget some information about. Thus enabling safe stack construction of !Sized
types.