diff --git a/src/doc/book/lifetimes.md b/src/doc/book/lifetimes.md index cb0757318984d..f7d9c94bc454f 100644 --- a/src/doc/book/lifetimes.md +++ b/src/doc/book/lifetimes.md @@ -290,7 +290,7 @@ lifetime parameters using three easily memorizable and unambiguous rules. This m acts as a shorthand for writing an item signature, while not hiding away the actual types involved as full local inference would if applied to it. -When talking about lifetime elision, we use the term *input lifetime* and +When talking about lifetime elision, we use the terms *input lifetime* and *output lifetime*. An *input lifetime* is a lifetime associated with a parameter of a function, and an *output lifetime* is a lifetime associated with the return value of a function. For example, this function has an input lifetime: @@ -335,11 +335,13 @@ fn print<'a>(s: &'a str); // expanded fn debug(lvl: u32, s: &str); // elided fn debug<'a>(lvl: u32, s: &'a str); // expanded +``` -// In the preceding example, `lvl` doesn’t need a lifetime because it’s not a -// reference (`&`). Only things relating to references (such as a `struct` -// which contains a reference) need lifetimes. +In the preceding example, `lvl` doesn’t need a lifetime because it’s not a +reference (`&`). Only things relating to references (such as a `struct` +which contains a reference) need lifetimes. +```rust,ignore fn substr(s: &str, until: u32) -> &str; // elided fn substr<'a>(s: &'a str, until: u32) -> &'a str; // expanded diff --git a/src/doc/book/ownership.md b/src/doc/book/ownership.md index c3e32e56c4266..23ca21b3b4992 100644 --- a/src/doc/book/ownership.md +++ b/src/doc/book/ownership.md @@ -214,7 +214,7 @@ 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. All primitive types implement the `Copy` trait and their ownership is -therefore not moved like one would assume, following the ´ownership rules´. +therefore not moved like one would assume, following the ‘ownership rules’. To give an example, the two following snippets of code only compile because the `i32` and `bool` types implement the `Copy` trait. @@ -290,6 +290,6 @@ let (v1, v2, answer) = foo(v1, v2); Ugh! The return type, return line, and calling the function gets way more complicated. -Luckily, Rust offers a feature, borrowing, which helps us solve this problem. -It’s the topic of the next section! +Luckily, Rust offers a feature which helps us solve this problem. +It’s called borrowing and is the topic of the next section! diff --git a/src/doc/book/references-and-borrowing.md b/src/doc/book/references-and-borrowing.md index ef339a1430989..57bfbce8b84de 100644 --- a/src/doc/book/references-and-borrowing.md +++ b/src/doc/book/references-and-borrowing.md @@ -123,7 +123,7 @@ let v = vec![]; foo(&v); ``` -errors with: +will give us this error: ```text error: cannot borrow immutable borrowed content `*v` as mutable @@ -152,8 +152,8 @@ the thing `y` points at. You’ll notice that `x` had to be marked `mut` as well If it wasn’t, we couldn’t take a mutable borrow to an immutable value. You'll also notice we added an asterisk (`*`) in front of `y`, making it `*y`, -this is because `y` is a `&mut` reference. You'll also need to use them for -accessing the contents of a reference as well. +this is because `y` is a `&mut` reference. You'll need to use astrisks to +access the contents of a reference as well. Otherwise, `&mut` references are like references. There _is_ a large difference between the two, and how they interact, though. You can tell @@ -179,7 +179,7 @@ As it turns out, there are rules. # The Rules -Here’s the rules about borrowing in Rust: +Here are the rules for borrowing in Rust: First, any borrow must last for a scope no greater than that of the owner. Second, you may have one or the other of these two kinds of borrows, but not @@ -208,12 +208,14 @@ With this in mind, let’s consider our example again. Here’s the code: ```rust,ignore -let mut x = 5; -let y = &mut x; +fn main() { + let mut x = 5; + let y = &mut x; -*y += 1; + *y += 1; -println!("{}", x); + println!("{}", x); +} ``` This code gives us this error: @@ -225,7 +227,7 @@ error: cannot borrow `x` as immutable because it is also borrowed as mutable ``` This is because we’ve violated the rules: we have a `&mut T` pointing to `x`, -and so we aren’t allowed to create any `&T`s. One or the other. The note +and so we aren’t allowed to create any `&T`s. It's one or the other. The note hints at how to think about this problem: ```text @@ -243,14 +245,16 @@ In Rust, borrowing is tied to the scope that the borrow is valid for. And our scopes look like this: ```rust,ignore -let mut x = 5; - -let y = &mut x; // -+ &mut borrow of x starts here - // | -*y += 1; // | - // | -println!("{}", x); // -+ - try to borrow x here - // -+ &mut borrow of x ends here +fn main() { + let mut x = 5; + + let y = &mut x; // -+ &mut borrow of x starts here + // | + *y += 1; // | + // | + println!("{}", x); // -+ - try to borrow x here +} // -+ &mut borrow of x ends here + ``` The scopes conflict: we can’t make an `&x` while `y` is in scope. @@ -269,12 +273,12 @@ println!("{}", x); // <- try to borrow x here ``` There’s no problem. Our mutable borrow goes out of scope before we create an -immutable one. But scope is the key to seeing how long a borrow lasts for. +immutable one. So scope is the key to seeing how long a borrow lasts for. ## Issues borrowing prevents Why have these restrictive rules? Well, as we noted, these rules prevent data -races. What kinds of issues do data races cause? Here’s a few. +races. What kinds of issues do data races cause? Here are a few. ### Iterator invalidation @@ -323,7 +327,7 @@ for i in &v { We can’t modify `v` because it’s borrowed by the loop. -### use after free +### Use after free References must not live longer than the resource they refer to. Rust will check the scopes of your references to ensure that this is true.