← Debugging Guides

阅读中文版本

Rust — E0382 use of moved value

Fix E0382 by cloning, borrowing instead of moving, or restructuring ownership so the value stays available.

beginnerdebuggingrustownership

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 -30

Interpretation

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();