Looking for a structured path? Browse all Rust lessons.

Maintained by
Learning Platform content team
Reviewed by
Learning Platform source and executable-example contract

Fix Rust E0382: use of moved value

The problem: E0382 means ownership of a non-Copy value moved somewhere else and the old binding was used afterward. The compiler is preventing two owners from trying to clean up the same allocation.

Reproduce the error

fn print_name(name: String) {
    println!("{name}");
}

fn main() {
    let name = String::from("Ferris");
    print_name(name);
    println!("Welcome, {name}");
}

print_name(name) takes the String by value. The compiler therefore rejects the final line with E0382: borrow of moved value: name.

Preferred fix: borrow when the function only reads

fn print_name(name: &str) {
    println!("{name}");
}

fn main() {
    let name = String::from("Ferris");
    print_name(&name);
    println!("Welcome, {name}");
}

Expected output:

Ferris
Welcome, Ferris

&name creates a shared borrow. The function can read the text but does not become its owner. Prefer &str over &String for read-only string parameters because it also accepts string literals and slices.

Other valid fixes

Clone only when you truly need a second owned allocation:

fn print_name(name: String) {
    println!("{name}");
}

fn main() {
    let name = String::from("Ferris");
    print_name(name.clone());
    println!("Welcome, {name}");
}

Or make the transfer deliberate and stop using the old binding. Types such as integers often do not trigger E0382 because they implement Copy; String, Vec<T>, and most heap-owning types do not.

Common failure mode

Adding .clone() everywhere makes code compile but can hide expensive allocation and a confused ownership design. First ask whether the callee needs ownership. If it only inspects the value, borrow it.

Run the failing and fixed versions in the Rust playground, study the ownership lesson, then continue with borrowing.

Official references