error[E0382]: borrow of moved value: `s`
You used a value after it was moved to another variable or function.
Why this happens
Rust enforces ownership rules at compile time β when you assign a heap-allocated value (like String) to another variable or pass it to a function, ownership transfers and the original binding becomes invalid. This prevents double-free bugs and data races. Types that implement the Copy trait (like i32) are exempt because theyβre cheaply duplicated on the stack.
Fix 1: Clone the value
let s = String::from("hello");
let s2 = s.clone(); // Clone instead of move
println!("{}", s); // Still valid
println!("{}", s2);
Fix 2: Use references
fn print_str(s: &String) {
println!("{}", s);
}
let s = String::from("hello");
print_str(&s); // Borrow, don't move
println!("{}", s); // Still valid
Fix 3: Use after move
// β s is moved
let s = String::from("hello");
let s2 = s;
println!("{}", s); // Error! s was moved
// β
Use s2 instead
println!("{}", s2);
Alternative solutions
Use Rc<T> or Arc<T> for shared ownership when multiple parts of your code need to own the same data:
use std::rc::Rc;
let s = Rc::new(String::from("hello"));
let s2 = Rc::clone(&s);
println!("{} {}", s, s2); // Both valid
Prevention
- Prefer borrowing (
&Tor&mut T) over transferring ownership whenever possible. - Use
#[clippy::pedantic]lints to catch unnecessary clones and ownership issues early.
Related resources
Related: Cargo Cheat Sheet