Sized trait and ?Sized for dynamically-sized types

Marcus Chen Jan 2026
1 tab
fn print_size<T: ?Sized>(value: &T) {
    // Can accept both &str and &String
    println!("Value: {:p}", value as *const T as *const ());
}

fn main() {
    let s = String::from("hello");
    print_size(&s);
    print_size("literal");
}
1 file · rust Explain with highlit

Most types in Rust are Sized (known size at compile time), which is an auto trait. Some types like str or [T] are !Sized (dynamically-sized types, DSTs). To work with DSTs, use &T or Box<T>. In generic code, T: Sized is the default bound. To accept DSTs, use T: ?Sized ("maybe sized"). I use ?Sized when writing generic functions for trait objects or slices. For example, a function taking &T where T: ?Sized can accept both &str and &String. Understanding Sized helps when you get confusing compiler errors about trait object sizes or return types. It's a subtle but important part of Rust's type system.