From 54abe4ce915d00ffc07d9077aebeedd052be29fa Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 14 Apr 2015 15:01:05 -0400 Subject: [PATCH 1/2] link to ownership for now --- src/doc/trpl/lifetimes.md | 2 +- src/doc/trpl/references-and-borrowing.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/trpl/lifetimes.md b/src/doc/trpl/lifetimes.md index c6eee97dc6a61..cfcd8c4ee155a 100644 --- a/src/doc/trpl/lifetimes.md +++ b/src/doc/trpl/lifetimes.md @@ -1,3 +1,3 @@ % Lifetimes -Coming soon! +Coming Soon! Until then, check out the [ownership](ownership.html) chapter. diff --git a/src/doc/trpl/references-and-borrowing.md b/src/doc/trpl/references-and-borrowing.md index 6acb326958d31..0e13ea612645c 100644 --- a/src/doc/trpl/references-and-borrowing.md +++ b/src/doc/trpl/references-and-borrowing.md @@ -1,3 +1,3 @@ % References and Borrowing -Coming Soon! +Coming Soon! Until then, check out the [ownership](ownership.html) chapter. From e5631f94b4963b08a726007fc775311bd95957f8 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Wed, 15 Apr 2015 11:34:39 -0400 Subject: [PATCH 2/2] TRPL: move semantics --- src/doc/trpl/move-semantics.md | 104 ++++++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/src/doc/trpl/move-semantics.md b/src/doc/trpl/move-semantics.md index 6917d7f8b8e0f..0e7a1130561eb 100644 --- a/src/doc/trpl/move-semantics.md +++ b/src/doc/trpl/move-semantics.md @@ -1,3 +1,105 @@ % Move Semantics -Coming Soon +An important aspect of [ownership][ownership] is ‘move semantics’. Move +semantics control how and when ownership is transferred between bindings. + +[ownership]: ownership.html + +For example, consider a type like `Vec`, which owns its contents: + +```rust +let v = vec![1, 2, 3]; +``` + +I can assign this vector to another binding: + +```rust +let v = vec![1, 2, 3]; + +let v2 = v; +``` + +But, if we try to use `v` afterwards, we get an error: + +```rust,ignore +let v = vec![1, 2, 3]; + +let v2 = v; + +println!("v[0] is: {}", v[0]); +``` + +It looks like this: + +```text +error: use of moved value: `v` +println!("v[0] is: {}", v[0]); + ^ +``` + +A similar thing happens if we define a function which takes ownership, and +try to use something after we’ve passed it as an argument: + +```rust +fn take(v: Vec) { + // what happens here isn’t important. +} + +let v = vec![1, 2, 3]; + +take(v); + +println!("v[0] is: {}", v[0]); +``` + +Same error: “use of moved value.” When we transfer ownership to something else, +we say that we’ve ‘moved’ the thing we refer to. You don’t need some sort of +special annotation here, it’s the default thing that Rust does. + +# The details + +The reason that we cannot use a binding after we’ve moved it is subtle, but +important. When we write code like this: + +```rust +let v = vec![1, 2, 3]; + +let v2 = v; +``` + +The first line creates some data for the vector on the stack, `v`. The vector’s +data, however, is stored on the heap, and so it contains a pointer to that +data. When we move `v` to `v2`, it creates a copy of that data, for `v2`. Which +would mean two pointers to the contents of the vector on the heap. That would +be a problem: it would violate Rust’s safety guarantees by introducing a data +race. Therefore, Rust forbids using `v` after we’ve done the move. + +It’s also important to note that optimizations may remove the actual copy of +the bytes, depending on circumstances. So it may not be as inefficient as it +initially seems. + +# `Copy` types + +We’ve established that when ownership is transferred to another binding, you +cannot use the original binding. However, there’s a [trait][traits] that changes this +behavior, and it’s called `Copy`. We haven’t discussed traits yet, but for now, +you can think of them as an annotation to a particular type that adds extra +behavior. For example: + +```rust +let v = 1; + +let v2 = v; + +println!("v is: {}", v); +``` + +In this case, `v` is an `i32`, which implements the `Copy` trait. This means +that, just like a move, when we assign `v` to `v2`, a copy of the data is made. +But, unlike a move, we can still use `v` afterward. This is because an `i32` +has no pointers to data somewhere else, copying it is a full copy. + +We will discuss how to make your own types `Copy` in the [traits][traits] +section. + +[traits]: traits.html