For instance,
struct Feet(i32);
struct Meters(i32);
fn hover(altitude: Meters) {
println!("At {} meters", altitude.0);
}
fn main() {
let altitude1 = Meters(16);
hover(altitude1);
let altitude2 = Feet(16);
hover(altitude2);
}
This fails at build time with: 12 | hover(altitude2);
| ----- ^^^^^^^^^ expected `Meters`, found `Feet`
| |
| arguments to this function are incorrect
Guaranteeing that I’ve never mixed units means I don’t have to worry about parking my spacecraft at 1/3 the expected altitude. Now I can concentrate on the rest of the logic. The language has my back on the types so I never have to waste brain cycles on the bookkeeping parts.That’s one example. It’s not unique to Rust by a long shot. But it’s still a vast improvement over C, where that same signed 32 bit data type is the number of eggs in a basket, the offset of bytes into a struct, the index of an array, a UTF-8 code point, or whatever else.
This really shows up at refactoring time. Move some Rust code around and it’ll loudly let you know exactly what you need to fix before it’s ready. C? Not so much.