Rust errors / Ownership and borrowing
Rust compiler error · checked with rustc 1.99.0
Rust error E0507: cannot move out of
What it meansYou tried to take ownership of a value you only have a reference to. Through a & you can read, copy or clone, but not move out.
What rustc prints
error[E0507]: cannot move out of dereference of `Ref<'_, TheDarkKnight>` --> main.rs:12:5 | 12 | x.borrow().nothing_is_true(); // error: cannot move out of borrowed content | ^^^^^^^^^^ ----------------- value moved due to this method call | | | move occurs because value has type `TheDarkKnight`, which does not implement the `Copy` trait | note: `TheDarkKnight::nothing_is_true` takes ownership of the receiver `self`, which moves value --> main.rs:6:24 | 6 | fn nothing_is_true(self) {} | ^^^^ note: if `TheDarkKnight` implemented `Clone`, you could clone the value --> main.rs:3:1 | 3 | struct TheDarkKnight; | ^^^^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type ... 12 | x.borrow().nothing_is_true(); // error: cannot move out of borrowed content | ---------- you could clone this value
Real output of rustc 1.99.0 compiling the official example below (2021 edition). Your names and line numbers will differ; the first line is the part to match.
Why it happens
let s = v[0];where the Vec holds Strings.- Matching on
&self.fieldand binding an owned String out of it. - Calling a method that takes
self(likeunwrap()onOption<String>) through a reference.
How to fix it
1. Borrow it
let s: &String = &v[0];2. Clone it
let s: String = v[0].clone();3. Take it and leave something behind
std::mem::take or Option::take moves out of a &mut.
let name = std::mem::take(&mut self.name);
let job = self.pending.take();4. Use as_ref() on Option
Turns &Option<T> into Option<&T>.
if let Some(n) = self.name.as_ref() { println!("{n}"); }Other wordings of this error
cannot move out of, which is behind a shared reference, move occurs because, cannot move out of index of, cannot move out of borrowed content
The compiler team's explanation
A borrowed value was moved out.
Erroneous code example:
use std::cell::RefCell;
struct TheDarkKnight;
impl TheDarkKnight {
fn nothing_is_true(self) {}
}
fn main() {
let x = RefCell::new(TheDarkKnight);
x.borrow().nothing_is_true(); // error: cannot move out of borrowed content
}
Here, the nothing_is_true method takes the ownership of self. However, self cannot be moved because .borrow() only provides an &TheDarkKnight, which is a borrow of the content owned by the RefCell. To fix this error, you have three choices:
- Try to avoid moving the variable.
- Somehow reclaim the ownership.
- Implement the
Copytrait on the type.
This can also happen when using a type implementing Fn or FnMut, as neither allows moving out of them (they usually represent closures which can be called more than once). Much of the text following applies equally well to non-FnOnce closure bodies.
Examples:
use std::cell::RefCell;
struct TheDarkKnight;
impl TheDarkKnight {
fn nothing_is_true(&self) {} // First case, we don't take ownership
}
fn main() {
let x = RefCell::new(TheDarkKnight);
x.borrow().nothing_is_true(); // ok!
}
Or:
use std::cell::RefCell;
struct TheDarkKnight;
impl TheDarkKnight {
fn nothing_is_true(self) {}
}
fn main() {
let x = RefCell::new(TheDarkKnight);
let x = x.into_inner(); // we get back ownership
x.nothing_is_true(); // ok!
}
Or:
use std::cell::RefCell;
#[derive(Clone, Copy)] // we implement the Copy trait
struct TheDarkKnight;
impl TheDarkKnight {
fn nothing_is_true(self) {}
}
fn main() {
let x = RefCell::new(TheDarkKnight);
x.borrow().nothing_is_true(); // ok!
}
Moving a member out of a mutably borrowed struct will also cause E0507 error:
struct TheDarkKnight;
impl TheDarkKnight {
fn nothing_is_true(self) {}
}
struct Batcave {
knight: TheDarkKnight
}
fn main() {
let mut cave = Batcave {
knight: TheDarkKnight
};
let borrowed = &mut cave;
borrowed.knight.nothing_is_true(); // E0507
}
It is fine only if you put something back. mem::replace can be used for that:
use std::mem;
let mut cave = Batcave {
knight: TheDarkKnight
};
let borrowed = &mut cave;
mem::replace(&mut borrowed.knight, TheDarkKnight).nothing_is_true(); // ok!
For more information on Rust's ownership system, take a look at the References & Borrowing section of the Book.
From rustc --explain E0507 (1.99.0), part of the Rust project, MIT or Apache-2.0. Official page.
Related errors
- E0382borrow of moved value
- E0499cannot borrow as mutable more than once at a time
- E0502cannot borrow as mutable because it is also borrowed as immutable
- E0106missing lifetime specifier
- E0505cannot move out of because it is borrowed
- E0506cannot assign to because it is borrowed
- E0508cannot move out of type `[NonCopy; 1]`, a non-copy array
- E0509cannot move out of type `DropStruct`, which implements the `Drop` trait
Up next
Often hit nextE0382: borrow of moved valueA related error from the same family.Read it next →Did this answer your question?