Zero cost can come in two forms (that come to my mind right now, feel free to comment with more): runtime and memory. You mentioned dynamic dispatch (when calling a vtable method) that _can_ be zero cost when using generics, the compiler will "inline" the type and know what method is being called. Note that there is a compile-time trade-off here, and the binary size would be larger than using `&dyn` (a pointer to a vtable).
To illustrate memory zero-cost, consider an optional boolean argument to a program. A boolean has two valid states, but used 8 bits of memory, defining `Option<bool>` would naively use one byte for the discriminant, and another for the value. Rust uses the niche optimization[0] to promise that this type will only use one byte of memory.
[0]https://google.github.io/comprehensive-rust/smart-pointers/b...