Use of moved value

Vulnerability potential None
DDoS potential None

The value was moved (ownership transferred) and is no longer usable here

Impact

This is a compile-time error (E0382): the program does not build, so there is no runtime effect. The developer must clone, borrow, or restructure ownership before the code compiles.

The check prevents the use-after-free / double-free family of bugs. After a non-Copy value is moved, the source binding is logically empty; reading it would alias memory now owned elsewhere, and dropping both the source and the destination would free the same resource twice. Rust statically guarantees each owned value is dropped exactly once by rejecting any use of a moved-from binding.

Vulnerability potential

None in safe Rust. The ownership/move analysis runs entirely at compile time and rejects the program, so no vulnerable binary is produced. Move semantics are a core part of how Rust statically eliminates double-free and use-after-free; this error is that guarantee firing as intended.

Technical details

When a value of a non-Copy type is assigned, passed by value, or returned, its ownership moves: the bytes are conceptually relocated to the new owner and the original binding is marked uninitialized by the move checker. Any subsequent read of the original is error[E0382]: borrow of moved value (or “use of moved value”). Types implementing Copy (integers, bool, char, shared references, small Copy structs) are duplicated bit-for-bit instead of moved, so they are never affected.

Closures and partial moves

The error also appears when a closure captures a value by move (move ||) and the surrounding code later uses it, and when one field of a struct is moved out, making the whole struct partially uninitialized and unusable as a whole.

Catching the issue

rustc/cargo check reports E0382 with notes showing where the move occurred and suggesting fixes. Resolutions, in rough order of preference: borrow instead of move (&value) when the callee does not need ownership; derive or implement Clone and call .clone() when an independent copy is acceptable; make a small value Copy; or redesign so ownership flows in one direction. clippy adds lints such as clippy::redundant_clone to avoid over-correcting with needless clones.

How to reproduce

Compile the following; the move checker rejects the second use with E0382.

fn main() {
    let s = String::from("hello");
    let t = s;             // ownership of the heap buffer moves from `s` to `t`
    println!("{t}");
    println!("{s}");       // error[E0382]: borrow of moved value: `s`
}