A dynamically sized type has no size the Rust compiler can determine at compile time. That does not necessarily mean its size changes while a program runs. A slice, written [T], represents some number of elements within an array, but [T] does not specify how many. section 6.3.2
A reference to a dynamically sized type carries more than a pointer. For a slice, it also needs a length: the pointer identifies where the elements begin, and the length tells Rust how far the slice extends. This information helps Rust keep accesses within the value’s space in memory. section 6.3.2 section 6.1
Keep three related ideas separate:
- A slice [T] is dynamically sized because its length is not part of the type. section 6.3.2
- String and Vec<T> can grow or shrink. That is a different reason to need memory whose amount is decided at runtime. section 6.3.2
- Heap allocation does not, by itself, make a type dynamically sized: Box<i32> puts an i32 on the heap, even though an i32 has a known size. section 6.3.2
Trait objects are another example of dynamically sized types. The slice is the simpler starting point: knowing where data begins is not enough when the compiler cannot determine how much data the value represents. section 6.3.2 section 6.1

