True 2D arrays "know" and enforce that every row has the same size. A vector of vectors allows every row to have a different size. You may in practice make them same size, but from perspective of the language that doesn't mean anything, and it will still track and check width of every row individually.
Vec of Vec is not a 2D array, but a 1D collection of unrelated 1D arrays.
Rust has an actual 2D array type as
[[i32; m] n], but these arrays in Rust have so many limitations that they're useless, so don't bother.
Rust doesn't have a 2D vec.
But every 1D collection can be tricked into storing 2D data efficiently. The trick is in addressing elements instead of
[x + width * y]. This is exactly what happens under the hood in languages that have 2D arrays. The computer memory is 1D, so they all have to do it like this anyway.