diff --git a/src/ch04-01-what-is-ownership.md b/src/ch04-01-what-is-ownership.md index 5249c2dd77..b8f14fd49e 100644 --- a/src/ch04-01-what-is-ownership.md +++ b/src/ch04-01-what-is-ownership.md @@ -113,12 +113,13 @@ hardcoded into the text of our program. The variable is valid from the point at which it’s declared until the end of the current *scope*. Listing 4-1 shows a program with comments annotating where the variable `s` would be valid. ++ ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-01/src/main.rs:here}} ``` -Listing 4-1: A variable and the scope in which it is -valid + In other words, there are two important points in time here: @@ -239,12 +240,13 @@ we’ve allocated on the heap. Let’s explore some of those situations now. Multiple variables can interact with the same data in different ways in Rust. Let’s look at an example using an integer in Listing 4-2. ++ ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-02/src/main.rs:here}} ``` -Listing 4-2: Assigning the integer value of variable `x` -to `y` + We can probably guess what this is doing: “bind the value `5` to `x`; then make a copy of the value in `x` and bind it to `y`.” We now have two variables, `x` @@ -429,14 +431,13 @@ assigning a value to a variable. Passing a variable to a function will move or copy, just as assignment does. Listing 4-3 has an example with some annotations showing where variables go into and out of scope. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-03/src/main.rs}} ``` -Listing 4-3: Functions with ownership and scope -annotated + If we tried to use `s` after the call to `takes_ownership`, Rust would throw a compile-time error. These static checks protect us from mistakes. Try adding @@ -449,14 +450,13 @@ Returning values can also transfer ownership. Listing 4-4 shows an example of a function that returns some value, with similar annotations as those in Listing 4-3. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-04/src/main.rs}} ``` -Listing 4-4: Transferring ownership of return -values + The ownership of a variable follows the same pattern every time: assigning a value to another variable moves it. When a variable that includes data on the @@ -471,13 +471,13 @@ from the body of the function that we might want to return as well. Rust does let us return multiple values using a tuple, as shown in Listing 4-5. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-05/src/main.rs}} ``` -Listing 4-5: Returning ownership of parameters + But this is too much ceremony and a lot of work for a concept that should be common. Luckily for us, Rust has a feature for using a value without diff --git a/src/ch04-02-references-and-borrowing.md b/src/ch04-02-references-and-borrowing.md index ea2d8d2029..04dd601c7d 100644 --- a/src/ch04-02-references-and-borrowing.md +++ b/src/ch04-02-references-and-borrowing.md @@ -12,12 +12,14 @@ particular type for the life of that reference. Here is how you would define and use a `calculate_length` function that has a reference to an object as a parameter instead of taking ownership of the value: -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-07-reference/src/main.rs:all}} ``` + + First, notice that all the tuple code in the variable declaration and the function return value is gone. Second, note that we pass `&s1` into `calculate_length` and, in its definition, we take `&String` rather than @@ -67,13 +69,13 @@ to give it back. You don’t own it. So, what happens if we try to modify something we’re borrowing? Try the code in Listing 4-6. Spoiler alert: it doesn’t work! -Filename: src/main.rs + ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-06/src/main.rs}} ``` -Listing 4-6: Attempting to modify a borrowed value + Here’s the error: @@ -89,12 +91,14 @@ allowed to modify something we have a reference to. We can fix the code from Listing 4-6 to allow us to modify a borrowed value with just a few small tweaks that use, instead, a *mutable reference*: -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-09-fixes-listing-04-06/src/main.rs}} ``` + + First we change `s` to be `mut`. Then we create a mutable reference with `&mut s` where we call the `change` function, and update the function signature to accept a mutable reference with `some_string: &mut String`. This makes it very @@ -104,12 +108,14 @@ Mutable references have one big restriction: if you have a mutable reference to a value, you can have no other references to that value. This code that attempts to create two mutable references to `s` will fail: -Filename: src/main.rs + ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/src/main.rs:here}} ``` + + Here’s the error: ```console @@ -198,12 +204,14 @@ reference to the data does. Let’s try to create a dangling reference to see how Rust prevents them with a compile-time error: -Filename: src/main.rs + ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-14-dangling-reference/src/main.rs}} ``` + + Here’s the error: ```console @@ -222,12 +230,14 @@ for it to be borrowed from Let’s take a closer look at exactly what’s happening at each stage of our `dangle` code: -Filename: src/main.rs + ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/src/main.rs:here}} ``` + + Because `s` is created inside `dangle`, when the code of `dangle` is finished, `s` will be deallocated. But we tried to return a reference to it. That means this reference would be pointing to an invalid `String`. That’s no good! Rust diff --git a/src/ch04-03-slices.md b/src/ch04-03-slices.md index 7f8c9b7af2..69fb35f82d 100644 --- a/src/ch04-03-slices.md +++ b/src/ch04-03-slices.md @@ -21,14 +21,13 @@ ownership, so this is fine. But what should we return? We don’t really have a way to talk about *part* of a string. However, we could return the index of the end of the word, indicated by a space. Let’s try that, as shown in Listing 4-7. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-07/src/main.rs:here}} ``` -Listing 4-7: The `first_word` function that returns a -byte index value into the `String` parameter + Because we need to go through the `String` element by element and check whether a value is a space, we’ll convert our `String` to an array of bytes using the @@ -73,14 +72,13 @@ because it’s a separate value from the `String`, there’s no guarantee that i will still be valid in the future. Consider the program in Listing 4-8 that uses the `first_word` function from Listing 4-7. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-08/src/main.rs:here}} ``` -Listing 4-8: Storing the result from calling the -`first_word` function and then changing the `String` contents + This program compiles without any errors and would also do so if we used `word` after calling `s.clear()`. Because `word` isn’t connected to the state of `s` @@ -176,12 +174,14 @@ let slice = &s[..]; With all this information in mind, let’s rewrite `first_word` to return a slice. The type that signifies “string slice” is written as `&str`: -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-18-first-word-slice/src/main.rs:here}} ``` + + We get the index for the end of the word the same way we did in Listing 4-7, by looking for the first occurrence of a space. When we find a space, we return a string slice using the start of the string and the index of the space as the @@ -207,12 +207,14 @@ string. Slices make this bug impossible and let us know we have a problem with our code much sooner. Using the slice version of `first_word` will throw a compile-time error: -Filename: src/main.rs + ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-19-slice-error/src/main.rs:here}} ``` + + Here’s the compiler error: ```console @@ -257,12 +259,13 @@ A more experienced Rustacean would write the signature shown in Listing 4-9 instead because it allows us to use the same function on both `&String` values and `&str` values. ++ ```rust,ignore {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-09/src/main.rs:here}} ``` -Listing 4-9: Improving the `first_word` function by using -a string slice for the type of the `s` parameter + If we have a string slice, we can pass that directly. If we have a `String`, we can pass a slice of the `String` or a reference to the `String`. This @@ -273,12 +276,14 @@ Methods”][deref-coercions] section of Chapter 15. Defining a function to take a string slice instead of a reference to a `String` makes our API more general and useful without losing any functionality: -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-09/src/main.rs:usage}} ``` + + ### Other Slices String slices, as you might imagine, are specific to strings. But there’s a