Move-After-Use Scenarios
Rust moves values on assignment, function call, and closure capture. Use references, Clone, or Copy types when you need multiple uses.
Recipe
error[E0382]: use of moved value: `v`
Working Example
// Before
let v = vec![1, 2];
let w = v;
println!("{:?}", v); // error
// After: borrow
let v = vec![1, 2];
let w = &v;
println!("{:?}", v);
// After: clone
let v = vec![1, 2];
let w = v.clone();Fn consume:
fn take(s: String) {}
let name = String::from("Ada");
take(name);
// use name again -> error; clone before take if neededClosure move:
let data = vec![1];
let c = move || data.len(); // data moved into closureDeep Dive
Copy types (integers, &T) duplicate instead of move. #[derive(Copy, Clone)] only when all fields Copy.
Gotchas
- Partial move of struct - other fields still valid unless whole struct moved.
- Iterator consume -
into_itermoves elements. - async block move - all captured owned vars move.
- Vec remove while iterating - use retain or indices reversed.
- expect Copy on String - not Copy; clone explicitly.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
&T arg | read-only reuse | callee needs ownership |
Rc | shared ownership | unique mutation without RefCell |
take() pattern | Option swap | always Some |
FAQs
partial move?
Field moved; access other fields ok if not partially moved struct in same binding pattern carefully.
fn once?
FnOnce consumes captures; use Fn/FnMut for borrow.
vec iter?
for x in v moves; use for x in &v to borrow.
match moves?
Binding by value moves; use ref in pattern ref x.
error E0382 hint?
Label shows move site and use site.
reuse in loop?
Recreate owned value each iteration or use references.
channel send?
Send moves value into channel.
return ownership?
Moving out of fn is intended; caller owns.
mem::replace?
Swap placeholder while building state machine.
when clone cheap?
Small strings at boundary; not in inner loop without measure.
Related
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.