Rust / Editorial solution guide
Resolve E0382: use of a moved value
Find the ownership transfer, choose whether the operation should borrow or consume, and verify the intended data flow without cloning by reflex.
Read-only knowledge base ยท No public comments
Recognize the symptoms
The compiler reports E0382 when code uses a value after an earlier operation moved it. The diagnostic usually points to the move and the later attempted use. This is a compilation rejection, not a runtime crash or a prediction that an old String prints empty text. No executable output should be attributed to the rejected program.
The issue can appear after assignment, a consuming function call, owned iteration, pattern destructuring, or moving captured data out of a closure. Identify the actual operation rather than assuming every ampersand or clone suggestion is the right repair.
Understand the likely causes
- String and Vec are not Copy. Assigning or passing them by value normally transfers ownership, leaving the old binding unavailable for further whole-value use. mut changes whether a binding permits mutation; it does not grant permission to reuse a moved value. Partial moves can also restrict an aggregate while leaving other fields usable.
- A signature taking String says it receives owned data. If it only observes text, that contract may be stronger than necessary. Copying an integer behaves differently because its type supports Copy. Explicit Clone behavior also depends on the type: String cloning creates independent text, while Rc and Arc cloning shares ownership of one allocation.
Locate the move before changing code
Follow the compiler span from the original binding to the consuming operation and the later use. This intentionally rejected excerpt passes an owned String into consume and then tries to print it. The function does not return that ownership. Adding mut to text cannot repair the contract. Keep this example non-runnable and use compiler checking, not execution, to understand the failure.
fn consume(text: String) -> usize { text.len() }
fn main() {
let text = String::from("note");
let _length = consume(text);
println!("{text}");
}
Intentionally rejected with E0382; no output is asserted.
Borrow when the operation only observes
Change the parameter to &str when the function only needs temporary read access. The complete correction below borrows the String and returns an independent byte count. The caller keeps ownership and can print the original text afterward. &str also accepts literals and valid text slices, making it a narrower ownership requirement than String. This is a semantic repair, not a workaround that merely hides the compiler error.
fn byte_count(text: &str) -> usize { text.len() }
fn main() {
let text = String::from("note");
let length = byte_count(&text);
println!("{text} {length}");
}
note 4
The String remains owned by main. The function only borrows it during the call and returns four bytes.
Keep consumption when ownership is required
If the function stores the String or sends it to a worker, taking ownership can be correct. Stop using the old binding, return ownership explicitly when that fits the operation, or clone before transfer when independent copies are required. For collections, choose iter for observation and owned into_iter for consumption. Do not add Clone bounds across an entire API merely to accommodate one call site, because that changes costs and accepted types for every consumer.
Verify the fix
Compile the corrected complete example with Rust 1.85+ and --edition=2024. It must print note 4 followed by a newline. Confirm the intended caller use remains after the observing function, so the test actually protects the repaired ownership requirement.
Use rustc --explain E0382 for official background and compile-only rejection tests if the project maintains them. Do not execute the invalid snippet. Also check that a supposed clone repair produces independent data when independence is the real requirement.
Keep it from recurring
- Read parameter and iterator ownership before writing calls. Document whether callbacks retain data, and distinguish shared-handle cloning from value snapshots. Prefer the least ownership transfer that fulfills the real lifetime requirement.