Rust does as much as possible at compile time, and some of its most famous features are entirely at compile time, but it will also use runtime checks where appropriate.
Some amount of runtime checking is inherent in any program. Even dependently typed programs must, for example, check input at runtime. They can make it easier to have absolutely minimal runtime checks, however. Rust is adding a limited form of dependent types for this reason.
Functions and types can take integers as monomorphization-time template parameters (const generics).
It would be nice if you could pass (n, t) where n is supplied at runtime, the type of t depends on the value of n, and the compiler only lets you use t if your code is valid for all reachable values of n.
eg. fn(n: usize, arr1: &[i32; n], arr2: &[i32, n]) allowed the function body to assume the two slices can be zipped without losing elements.
Note that i don't have enough experience with either dependent types, zz, or wuffs to explain much further.
> Functions and types can take integers as monomorphization-time template parameters (const generics).
Const generics aren't dependent types though; you're still dealing with known constants at compile time. For it to be dependent types, you need something like in your latter example, where a type is dependent on an actual _value_ passed to a function at runtime.
> eg. fn(n: usize, arr1: &[i32; n], arr2: &[i32, n]) allowed the function body to assume the two slices can be zipped without losing elements.
Often you can wrangle the optimizer into eliminating all but one bounds check by passing slices instead and then slicing one of the inputs in terms of length of the other. The Zip iterator adapter also has optimizations for the case of two slices where iteration will only require two length queries at the beginning and no further bounds checks.
Some amount of runtime checking is inherent in any program. Even dependently typed programs must, for example, check input at runtime. They can make it easier to have absolutely minimal runtime checks, however. Rust is adding a limited form of dependent types for this reason.