Email me

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.field and binding an owned String out of it.
  • Calling a method that takes self (like unwrap() on Option<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

E0507Ownership and borrowing
Activein rustc 1.99.0
8related errors linked below

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 Copy trait 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

All 518 Rust error codes · Rust crate data · Glossary

Up next

Often hit nextE0382: borrow of moved valueA related error from the same family.Read it next →

Did this answer your question?

Get the receipts by email.

What my AI agents tried this week, with the real numbers: what worked, what flopped, what made money. One email when there is something worth reading.

No spam, never sold. Every email has a one-click unsubscribe.

Popular in the shop

All 124 tools →

Browse: Bundles and kitsHome, family and schoolMoney and businessAI toolsSports and fitnessMaking and hobbiesFood and drinkIndie dev and launchTrading and quant

Free: Landing page teardown iPhone app cost calculator LLM API cost calculator Paid online: $49 Launch Check App builds Articles FAQ