Why Rust Complains About Borrow and How to Fix It? Full Breakdown

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: The moment when Rust "doesn't understand" you

\n

You're writing in Rust. Everything is going well. The compiler is silent. You feel like a memory master. And then — bam! — it appears:

\n
error[E0507]: cannot move out of borrowed content\n  --> src/main.rs:10:9\n   |\n10 |         let value = self.data;\n   |                     ^^^^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait\n
\n

Or its close relative:

\n
error[E0507]: cannot move out of `*self` which is behind a shared reference\n
\n

If you're a beginner, this looks like a magical curse. If you're experienced, you know it's just another lesson from the Borrow Checker.

\n

In this article, we'll break down what these errors mean, why Rust is so strict, and — most importantly — how to fix them with live code examples. This is not boring theory, but a practical survival guide in the world of ownership and borrowing.

\n\n

The gist: Ownership, borrowing, and "move"

\n

Before diving into the details, let's recall the three pillars of Rust:

\n
    \n
  • Ownership: Every value in Rust has exactly one owner.
  • \n
  • Borrowing: You can "borrow" a value via a reference (&T — immutable, &mut T — mutable), without taking ownership.
  • \n
  • Move: When you assign a value to a new variable or pass it to a function without &, ownership is moved. The original variable becomes invalid.
  • \n
\n

The error cannot move out of borrowed content occurs precisely when you try to move a value for which you only have a reference (&T). Rust forbids this because after the move, the reference would become a dangling pointer. And Rust, as you know, does not forgive such things.

\n\n

Scenario 1: Attempting to move a struct field via &self

\n

The most common case. You have a struct, and you want to return one of its fields from a method that takes &self.

\n\n

Code with error

\n
struct User {\n    name: String,\n    age: u32,\n}\n\nimpl User {\n    // Trying to give away name "for good"\n    fn give_name(&self) -> String {\n        self.name // ERROR!\n    }\n}\n\nfn main() {\n    let user = User { name: "Alice".to_string(), age: 30 };\n    let name = user.give_name();\n    println!("{}", name);\n}\n
\n

The compiler will say:

\n
error[E0507]: cannot move out of `self.name` which is behind a shared reference\n
\n

Why? self is &User. We don't own self, we only borrowed it. Attempting to move self.name (type String, which does not implement Copy) means that after the method call, the owner (user) would lose its field. But the reference &self still exists! Rust protects us from disaster.

\n\n

How to fix?

\n

There are three main ways, depending on your task.

\n\n

Method 1: Cloning (simplest, but not always efficient)

\n

If you need the value itself, not a reference, and you're willing to pay for copying:

\n
fn give_name(&self) -> String {\n    self.name.clone() // Works! Creates a copy.\n}\n
\n

Downside: clone() for String makes a full copy of the heap data. On large strings, this is expensive.

\n\n

Method 2: Returning a reference (changing the signature)

\n

If the calling code only needs a reference to the field:

\n
fn give_name(&self) -> &String {\n    &self.name // Return a reference, no move\n}\n
\n

Now we're not moving, but borrowing. All is fair. The calling code will get a

Blogs

Book Recommendations