error[E0277]: the size for values of type `str` cannot be known at compilation time
ID: rust/e0277-str-not-sized
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| 1 | active | — | — | — |
Root Cause
The type `str` is a dynamically sized type (DST) -- its size is not known at compile time because strings can be any length. Rust requires all local variables, function parameters, and return types to be Sized by default. You cannot use `str` directly; you must use it behind a pointer: `&str` (borrowed string slice), `String` (owned heap string), or `Box<str>` (owned boxed slice). This is one of the most common errors for Rust beginners encountering the Sized trait bound system.
genericWorkarounds
-
95% success Use &str for borrowed string references (most common fix)
// Before (error): fn greet(name: str) { // E0277: str is not Sized println!("Hello, {name}"); } // After: use a reference fn greet(name: &str) { println!("Hello, {name}"); } // For struct fields: struct Config<'a> { name: &'a str, // Borrowed string slice with lifetime } let cfg = Config { name: "production" };Sources: https://doc.rust-lang.org/book/ch04-03-slices.html#string-slices
-
93% success Use String for owned string data
// When you need ownership (e.g., storing in a struct without lifetimes): struct User { name: String, // Owned, heap-allocated, Sized } impl User { fn new(name: &str) -> Self { User { name: name.to_string() } } } // For function parameters that need ownership: fn store_name(name: String) { // name is owned and can be stored }Sources: https://doc.rust-lang.org/book/ch08-02-strings.html
-
80% success Use Box<str> for owned string data with minimal overhead
// Box<str> is a thin pointer + length, slightly smaller than String // (no capacity field). Useful for immutable owned strings: let boxed: Box<str> = "hello".into(); let boxed: Box<str> = String::from("hello").into_boxed_str(); // In generic contexts with ?Sized bound: fn print_it<T: AsRef<str> + ?Sized>(val: &T) { println!("{}", val.as_ref()); } print_it("literal"); // &str print_it(&String::from("owned")); // &StringSources: https://doc.rust-lang.org/std/boxed/struct.Box.html
Dead Ends
Common approaches that don't work:
-
Add #[repr(C)] or other layout attributes to make str Sized
95% fail
repr attributes control memory layout of structs and enums, not the fundamental property of str being a dynamically-sized type. str is an unsized type at the language level -- it represents a UTF-8 byte sequence of unknown length. No attribute can change this; it is intrinsic to how str is defined in the language.
-
Use str as a struct field type directly without indirection
90% fail
Struct fields must be Sized (unless the very last field uses ?Sized). Declaring `field: str` makes the entire struct unsized, which means it cannot be stack-allocated, returned from functions, or used as a local variable. The struct becomes essentially unusable without Box or other indirection for the entire struct.