Use a tuple struct wrapping the inner type to create a distinct type that the compiler treats as unique, preventing accidental misuse while adding zero runtime overhead.
struct Millimeters(u32);
struct Meters(u32);
fn add_lengths(meters: Meters, millimeters: Millimeters) -> u32 {
meters.0 * 1000 + millimeters.0
}
fn main() {
let a = Millimeters(500);
let b = Meters(1);
// let c = add_lengths(a, b); // Error: expected Meters, found Millimeters
let total = add_lengths(b, a);
println!("Total: {}", total);
}
This pattern allows you to implement traits for the wrapper that the inner type doesn't support, or hide the inner type's API entirely.