AnyCompiler

Ownership

Every value in Rust has exactly one owner at a time. When the owner goes out of scope, the value is dropped (its memory freed) automatically — no garbage collector, no manual free(). This single rule is what lets Rust guarantee memory safety entirely at compile time.

Copy types vs. moves

Simple types like i32 implement the Copy trait, so assigning one variable to another just copies the value — both remain independently usable.

fn main() {
    let x = 5;
    let y = x; // i32 is Copy, so x is still valid
    println!("x = {}, y = {}", x, y);
}
Output
x = 5, y = 5

A String doesn't implement Copy, because it owns heap-allocated data. Assigning s1 to s2 moves ownership — s1 is no longer valid after this, which avoids both variables trying to free the same memory later.

fn main() {
    let s1 = String::from("hello");
    let s2 = s1; // s1 is moved into s2

    println!("{}", s2);
}
Output
hello

What a real move error looks like

This is genuinely what rustc reports when you try to use a value after it's been moved — captured from a real run, not written to look plausible:

fn main() {
    let s1 = String::from("hello");
    let s2 = s1;

    println!("{}, world!", s1);
}
Output
error[E0382]: borrow of moved value: `s1`
 --> main.rs:5:28
  |
2 |     let s1 = String::from("hello");
  |         -- move occurs because `s1` has type `std::string::String`, which does not implement the `Copy` trait
3 |     let s2 = s1;
  |              -- value moved here
4 | 
5 |     println!("{}, world!", s1);
  |                            ^^ value borrowed here after move

error: aborting due to previous error

For more information about this error, try `rustc --explain E0382`.

Nothing runs at all — no output, just the error. This is the whole point: Rust catches a would-be use-after-free at compile time, in a language with no garbage collector to clean up the mess if it slipped through.

Next: references and borrowing — how to use a value without taking ownership of it.

Practice exercise

Create a String name = String::from("Alice"). Move it into a new variable owner, then print owner (not name).