Rust — E0382 use of moved value
Fix E0382 by cloning, borrowing instead of moving, or restructuring ownership so the value stays available.
Symptoms
- error[E0382]: use of moved value: `s`
- The value was passed to a function that took ownership
- Using a String after pushing it into a collection fails
- A loop moves a value on the first iteration
Possible causes
- A non-Copy value was moved and later used
- A function takes ownership so the caller can no longer use the value
- Inserting into a collection moves the value
- A closure captured by move then the value is used again
Diagnosis steps
Read where the value was moved
cargo build 2>&1 | head -30Interpretation
The compiler shows the move location and the later use, pinpointing exactly where ownership changed.
Borrow instead of moving
fn len(s: &String) -> usize; len(&s);Interpretation
Changing the function to take a reference lets the caller keep the value.
Clone when both sides need ownership
let s2 = s.clone();Interpretation
Cloning produces an independent value when you genuinely need two owned copies, at some cost.
Root cause
A value was moved to a new owner and then used in its original location, where it no longer exists because Rust moves, not copies, non-Copy types by default.
Fix
Borrow the value instead of moving it, clone it when both locations need ownership, or restructure so the move happens after the last use.
Verify the fix
Rebuild and confirm the error is gone, then run tests to confirm the value is used correctly and any clone did not change behavior.
Symptom walkthrough
The compiler reports E0382, use of moved value, and points at both where the value was moved and where it was used afterward. Rust moves non-Copy values by default, so passing a String to a function that takes ownership ends the caller access. The error is precise and usually means the design needs a borrow, a clone, or a reordering of uses.
Fix in practice
Take a reference where ownership is not needed, clone when two owners are genuinely required, or move the value after its last use. Reaching for Clone everywhere works but adds cost and allocations, so prefer borrowing when the function only reads the value.
Verification
Rebuild and confirm the error is gone, then run the tests and confirm the value is handled correctly. Passing tests with expected data confirm the ownership decision was right, not just compilable.
Diagnostic commands
Check the behavior with commands like these:
cargo build 2>&1 | head -30
fn len(s: &String) -> usize; len(&s);
let s2 = s.clone();