diff --git a/second-edition/nostarch/chapter05.md b/second-edition/nostarch/chapter05.md index 9d45b04d9..e28ce9766 100644 --- a/second-edition/nostarch/chapter05.md +++ b/second-edition/nostarch/chapter05.md @@ -62,14 +62,27 @@ Listing 5-2: Creating an instance of the `User` struct To get a specific value from a struct, we can use dot notation. If we wanted just this user’s email address, we can use `user1.email` wherever we want to use this value. To change a value in a struct, if the instance is mutable, we -can use the dot notation and assign into a particular field, such as -`user1.email = String::from("someone-else@example.com");`. +can use the dot notation and assign into a particular field. Listing 5-3 shows +how to change the value in the `email` field of a mutable `User` instance: + +``` +let mut user1 = User { + email: String::from("someone@example.com"), + username: String::from("someusername123"), + active: true, + sign_in_count: 1, +}; + +user1.email = String::from("anotheremail@example.com"); +``` + +Listing 5-3: Changing the value in the `email` field of a `User` instance ### Field Init Shorthand when Variables Have the Same Name as Fields If you have variables with the same names as struct fields, you can use *field init shorthand*. This can make functions that create new instances of structs -more concise. The function named `build_user` shown here in Listing 5-3 has +more concise. The function named `build_user` shown here in Listing 5-4 has parameters named `email` and `username`. The function creates and returns a `User` instance: @@ -84,13 +97,14 @@ fn build_user(email: String, username: String) -> User { } ``` -Listing 5-3: A `build_user` function that takes an email and username and +Listing 5-4: A `build_user` function that takes an email and username and returns a `User` instance Because the parameter names `email` and `username` are the same as the `User` + struct’s field names `email` and `username`, we can write `build_user` without -the repetition of `email` and `username` as shown in Listing 5-4. This version -of `build_user` behaves the same way as the one in Listing 5-3. The field init +the repetition of `email` and `username` as shown in Listing 5-5. This version +of `build_user` behaves the same way as the one in Listing 5-4. The field init syntax can make cases like this shorter to write, especially when structs have many fields. @@ -105,13 +119,13 @@ fn build_user(email: String, username: String) -> User { } ``` -Listing 5-4: A `build_user` function that uses field init syntax since the +Listing 5-5: A `build_user` function that uses field init syntax since the `email` and `username` parameters have the same name as struct fields ### Creating Instances From Other Instances With Struct Update Syntax It’s often useful to create a new instance from an old instance, using most of -the old instance’s values but changing some. Listing 5-5 shows an example of +the old instance’s values but changing some. Listing 5-6 shows an example of creating a new `User` instance in `user2` by setting the values of `email` and `username` but using the same values for the rest of the fields from the `user1` instance we created in Listing 5-2: @@ -125,13 +139,13 @@ let user2 = User { }; ``` -Listing 5-5: Creating a new `User` instance, `user2`, and setting some fields +Listing 5-6: Creating a new `User` instance, `user2`, and setting some fields to the values of the same fields from `user1` The *struct update syntax* achieves the same effect as the code in Listing -5-5 using less code. The struct update syntax uses `..` to specify that the +5-6 using less code. The struct update syntax uses `..` to specify that the remaining fields not set explicitly should have the same value as the fields in -the given instance. The code in Listing 5-6 also creates an instance in `user2` +the given instance. The code in Listing 5-7 also creates an instance in `user2` that has a different value for `email` and `username` but has the same values for the `active` and `sign_in_count` fields that `user1` has: @@ -143,7 +157,7 @@ let user2 = User { }; ``` -Listing 5-6: Using struct update syntax to set a new `email` and `username` +Listing 5-7: Using struct update syntax to set a new `email` and `username` values for a `User` instance but use the rest of the values from the fields of the instance in the `user1` variable @@ -242,7 +256,7 @@ refactor the program until we’re using structs instead. Let’s make a new binary project with Cargo called *rectangles* that will take the length and width of a rectangle specified in pixels and will calculate the -area of the rectangle. Listing 5-7 shows a short program with one way of doing +area of the rectangle. Listing 5-8 shows a short program with one way of doing just that in our project’s *src/main.rs*: Filename: src/main.rs @@ -263,7 +277,7 @@ fn area(length: u32, width: u32) -> u32 { } ``` -Listing 5-7: Calculating the area of a rectangle specified by its length and +Listing 5-8: Calculating the area of a rectangle specified by its length and width in separate variables Now, run this program using `cargo run`: @@ -274,7 +288,7 @@ The area of the rectangle is 1500 square pixels. ### Refactoring with Tuples -Even though Listing 5-7 works and figures out the area of the rectangle by +Even though Listing 5-8 works and figures out the area of the rectangle by calling the `area` function with each dimension, we can do better. The length and the width are related to each other because together they describe one rectangle. @@ -290,7 +304,7 @@ function we wrote has two parameters. The parameters are related, but that’s not expressed anywhere in our program. It would be more readable and more manageable to group length and width together. We’ve already discussed one way we might do that in the Grouping Values into Tuples section of Chapter 3 on -page XX: by using tuples. Listing 5-8 shows another version of our program that +page XX: by using tuples. Listing 5-9 shows another version of our program that uses tuples: Filename: src/main.rs @@ -329,7 +343,7 @@ our code. We use structs to add meaning by labeling the data. We can transform the tuple we’re using into a data type with a name for the whole as well as names for the -parts, as shown in Listing 5-9: +parts, as shown in Listing 5-10: Filename: src/main.rs @@ -353,7 +367,7 @@ fn area(rectangle: &Rectangle) -> u32 { } ``` -Listing 5-9: Defining a `Rectangle` struct +Listing 5-10: Defining a `Rectangle` struct Here we’ve defined a struct and named it `Rectangle`. Inside the `{}` we defined the fields as `length` and `width`, both of which have type `u32`. Then @@ -378,7 +392,7 @@ of `0` and `1`—a win for clarity. It would be helpful to be able to print out an instance of the `Rectangle` while we’re debugging our program in order to see the values for all its -fields. Listing 5-10 uses the `println!` macro as we have been in earlier +fields. Listing 5-11 uses the `println!` macro as we have been in earlier chapters: Filename: src/main.rs @@ -396,7 +410,7 @@ fn main() { } ``` -Listing 5-10: Attempting to print a `Rectangle` instance +Listing 5-11: Attempting to print a `Rectangle` instance When we run this code, we get an error with this core message: @@ -443,7 +457,7 @@ crate, add `#[derive(Debug)]` or manually implement it Rust *does* include functionality to print out debugging information, but we have to explicitly opt-in to make that functionality available for our struct. To do that, we add the annotation `#[derive(Debug)]` just before the struct -definition, as shown in Listing 5-11: +definition, as shown in Listing 5-12: Filename: src/main.rs @@ -461,7 +475,7 @@ fn main() { } ``` -Listing 5-11: Adding the annotation to derive the `Debug` trait and printing +Listing 5-12: Adding the annotation to derive the `Debug` trait and printing the `Rectangle` instance using debug formatting Now when we run the program, we won’t get any errors and we’ll see the @@ -498,7 +512,7 @@ continue to refactor this code by turning the `area` function into an `area` ## Method Syntax *Methods* are similar to functions: they’re declared with the `fn` keyword and -their name, they can have parameters and return values, and they contain some +their name, they can have parameters and a return value, and they contain some code that is run when they’re called from somewhere else. However, methods are different from functions in that they’re defined within the context of a struct (or an enum or a trait object, which we cover in Chapters 6 and 17, @@ -509,7 +523,7 @@ instance of the struct the method is being called on. Let’s change the `area` function that has a `Rectangle` instance as a parameter and instead make an `area` method defined on the `Rectangle` struct, as shown -in Listing 5-12: +in Listing 5-13: Filename: src/main.rs @@ -536,7 +550,7 @@ fn main() { } ``` -Listing 5-12: Defining an `area` method on the `Rectangle` struct +Listing 5-13: Defining an `area` method on the `Rectangle` struct To define the function within the context of `Rectangle`, we start an `impl` (*implementation*) block. Then we move the `area` function within the `impl` @@ -608,7 +622,7 @@ Let’s practice using methods by implementing a second method on the `Rectangle struct. This time, we want an instance of `Rectangle` to take another instance of `Rectangle` and return `true` if the second `Rectangle` can fit completely within `self`; otherwise it should return `false`. That is, we want to be able -to write the program shown in Listing 5-13, once we’ve defined the `can_hold` +to write the program shown in Listing 5-14, once we’ve defined the `can_hold` method: Filename: src/main.rs @@ -624,7 +638,7 @@ fn main() { } ``` -Listing 5-13: Demonstration of using the as-yet-unwritten `can_hold` method +Listing 5-14: Demonstration of using the as-yet-unwritten `can_hold` method And the expected output would look like the following, because both dimensions of `rect2` are smaller than the dimensions of `rect1`, but `rect3` is wider @@ -647,7 +661,7 @@ calling the `can_hold` method. The return value of `can_hold` will be a boolean, and the implementation will check whether the length and width of `self` are both greater than the length and width of the other `Rectangle`, respectively. Let’s add the new `can_hold` method to the `impl` block from -Listing 5-12, shown in Listing 5-14: +Listing 5-13, shown in Listing 5-15: Filename: src/main.rs @@ -663,10 +677,10 @@ impl Rectangle { } ``` -Listing 5-14: Implementing the `can_hold` method on `Rectangle` that takes +Listing 5-15: Implementing the `can_hold` method on `Rectangle` that takes another `Rectangle` instance as a parameter -When we run this code with the `main` function in Listing 5-13, we’ll get our +When we run this code with the `main` function in Listing 5-14, we’ll get our desired output. Methods can take multiple parameters that we add to the signature after the `self` parameter, and those parameters work just like parameters in functions. diff --git a/second-edition/nostarch/odt/chapter05.docx b/second-edition/nostarch/odt/chapter05.docx index f657e777e..d2b3a79fa 100644 Binary files a/second-edition/nostarch/odt/chapter05.docx and b/second-edition/nostarch/odt/chapter05.docx differ diff --git a/second-edition/nostarch/odt/chapter11.docx b/second-edition/nostarch/odt/chapter11.docx new file mode 100644 index 000000000..2dbdf68c4 Binary files /dev/null and b/second-edition/nostarch/odt/chapter11.docx differ diff --git a/second-edition/nostarch/odt/chapter12.docx b/second-edition/nostarch/odt/chapter12.docx new file mode 100644 index 000000000..00531775b Binary files /dev/null and b/second-edition/nostarch/odt/chapter12.docx differ diff --git a/second-edition/src/appendix-06-translation.md b/second-edition/src/appendix-06-translation.md index 5500004dd..c82e288da 100644 --- a/second-edition/src/appendix-06-translation.md +++ b/second-edition/src/appendix-06-translation.md @@ -6,8 +6,10 @@ For resources in languages other than English. Most are still in progress; see [label]: https://github.com/rust-lang/book/issues?q=is%3Aopen+is%3Aissue+label%3ATranslations - [Português](https://coreh.github.io/rust-book-pt-br/) -- [Tiếng việt](https://rust-vietnam.github.io/book/) +- [Tiếng việt](https://github.com/hngnaig/rust-lang-book/tree/vi-VN) - [简体中文](http://www.broadview.com.cn/article/144), [alternate](https://github.com/KaiserY/trpl-zh-cn) - [українська мова](https://github.com/pavloslav/rust-book-uk-ua) - [Español](https://github.com/z1mvader/book) -- [Italiano](https://github.com/CodelessFuture/trpl2-it) \ No newline at end of file +- [Italiano](https://github.com/CodelessFuture/trpl2-it) +- [Русский](https://github.com/iDeBugger/rust-book-ru) +- [한국어](https://github.com/rinthel/rust-lang-book-ko) diff --git a/second-edition/src/ch01-01-installation.md b/second-edition/src/ch01-01-installation.md index 6a6f27240..4be5ed6a3 100644 --- a/second-edition/src/ch01-01-installation.md +++ b/second-edition/src/ch01-01-installation.md @@ -30,6 +30,19 @@ Rust is installed now. Great! Of course, if you disapprove of the `curl | sh` pattern, you can download, inspect and run the script however you like. +The installation script automatically adds Rust to your system PATH after your next login. +If you want to start using Rust right away, run the following command in your shell: + +```text +$ source $HOME/.cargo/env +``` + +Alternatively, add the following line to your `~/.bash_profile`: + +```text +$ export PATH="$HOME/.cargo/bin:$PATH" +``` + ### Installing on Windows On Windows, go to [https://rustup.rs](https://rustup.rs/) and diff --git a/second-edition/src/ch04-01-what-is-ownership.md b/second-edition/src/ch04-01-what-is-ownership.md index c427ccd1c..31cf4004b 100644 --- a/second-edition/src/ch04-01-what-is-ownership.md +++ b/second-edition/src/ch04-01-what-is-ownership.md @@ -327,7 +327,7 @@ use `s1` after `s2` is created: let s1 = String::from("hello"); let s2 = s1; -println!("{}", s1); +println!("{}, world!", s1); ``` You’ll get an error like this because Rust prevents you from using the diff --git a/second-edition/src/ch05-01-defining-structs.md b/second-edition/src/ch05-01-defining-structs.md index e75255bfd..c67419b94 100644 --- a/second-edition/src/ch05-01-defining-structs.md +++ b/second-edition/src/ch05-01-defining-structs.md @@ -55,14 +55,35 @@ struct To get a specific value from a struct, we can use dot notation. If we wanted just this user’s email address, we can use `user1.email` wherever we want to use this value. To change a value in a struct, if the instance is mutable, we -can use the dot notation and assign into a particular field, such as -`user1.email = String::from("someone-else@example.com");`. +can use the dot notation and assign into a particular field. Listing 5-3 shows +how to change the value in the `email` field of a mutable `User` instance: + +```rust +# struct User { +# username: String, +# email: String, +# sign_in_count: u64, +# active: bool, +# } +# +let mut user1 = User { + email: String::from("someone@example.com"), + username: String::from("someusername123"), + active: true, + sign_in_count: 1, +}; + +user1.email = String::from("anotheremail@example.com"); +``` + +Listing 5-3: Changing the value in the `email` field of a +`User` instance ### Field Init Shorthand when Variables Have the Same Name as Fields If you have variables with the same names as struct fields, you can use *field init shorthand*. This can make functions that create new instances of structs -more concise. The function named `build_user` shown here in Listing 5-3 has +more concise. The function named `build_user` shown here in Listing 5-4 has parameters named `email` and `username`. The function creates and returns a `User` instance: @@ -84,13 +105,13 @@ fn build_user(email: String, username: String) -> User { } ``` -Listing 5-3: A `build_user` function that takes an email +Listing 5-4: A `build_user` function that takes an email and username and returns a `User` instance Because the parameter names `email` and `username` are the same as the `User` struct's field names `email` and `username`, we can write `build_user` without -the repetition of `email` and `username` as shown in Listing 5-4. This version -of `build_user` behaves the same way as the one in Listing 5-3. The field init +the repetition of `email` and `username` as shown in Listing 5-5. This version +of `build_user` behaves the same way as the one in Listing 5-4. The field init syntax can make cases like this shorter to write, especially when structs have many fields. @@ -112,14 +133,14 @@ fn build_user(email: String, username: String) -> User { } ``` -Listing 5-4: A `build_user` function that uses field init +Listing 5-5: A `build_user` function that uses field init syntax since the `email` and `username` parameters have the same name as struct fields ### Creating Instances From Other Instances With Struct Update Syntax It's often useful to create a new instance from an old instance, using most of -the old instance's values but changing some. Listing 5-5 shows an example of +the old instance's values but changing some. Listing 5-6 shows an example of creating a new `User` instance in `user2` by setting the values of `email` and `username` but using the same values for the rest of the fields from the `user1` instance we created in Listing 5-2: @@ -147,13 +168,13 @@ let user2 = User { }; ``` -Listing 5-5: Creating a new `User` instance, `user2`, and +Listing 5-6: Creating a new `User` instance, `user2`, and setting some fields to the values of the same fields from `user1` - The *struct update syntax* achieves the same effect as the code in Listing -5-5 using less code. The struct update syntax uses `..` to specify that the +The *struct update syntax* achieves the same effect as the code in Listing 5-6 +using less code. The struct update syntax uses `..` to specify that the remaining fields not set explicitly should have the same value as the fields in -the given instance. The code in Listing 5-6 also creates an instance in `user2` +the given instance. The code in Listing 5-7 also creates an instance in `user2` that has a different value for `email` and `username` but has the same values for the `active` and `sign_in_count` fields that `user1` has: @@ -179,7 +200,7 @@ let user2 = User { }; ``` -Listing5-6: Using struct update syntax to set a new +Listing 5-7: Using struct update syntax to set a new `email` and `username` values for a `User` instance but use the rest of the values from the fields of the instance in the `user1` variable diff --git a/second-edition/src/ch05-02-example-structs.md b/second-edition/src/ch05-02-example-structs.md index 6ce3b85b0..09f37dbfd 100644 --- a/second-edition/src/ch05-02-example-structs.md +++ b/second-edition/src/ch05-02-example-structs.md @@ -6,7 +6,7 @@ refactor the program until we’re using structs instead. Let’s make a new binary project with Cargo called *rectangles* that will take the length and width of a rectangle specified in pixels and will calculate the -area of the rectangle. Listing 5-7 shows a short program with one way of doing +area of the rectangle. Listing 5-8 shows a short program with one way of doing just that in our project’s *src/main.rs*: Filename: src/main.rs @@ -27,7 +27,7 @@ fn area(length: u32, width: u32) -> u32 { } ``` -Listing 5-7: Calculating the area of a rectangle +Listing 5-8: Calculating the area of a rectangle specified by its length and width in separate variables Now, run this program using `cargo run`: @@ -38,7 +38,7 @@ The area of the rectangle is 1500 square pixels. ### Refactoring with Tuples -Even though Listing 5-7 works and figures out the area of the rectangle by +Even though Listing 5-8 works and figures out the area of the rectangle by calling the `area` function with each dimension, we can do better. The length and the width are related to each other because together they describe one rectangle. @@ -54,7 +54,7 @@ function we wrote has two parameters. The parameters are related, but that’s not expressed anywhere in our program. It would be more readable and more manageable to group length and width together. We’ve already discussed one way we might do that in the Grouping Values into Tuples section of Chapter 3 on -page XX: by using tuples. Listing 5-8 shows another version of our program that +page XX: by using tuples. Listing 5-9 shows another version of our program that uses tuples: Filename: src/main.rs @@ -94,7 +94,7 @@ our code. We use structs to add meaning by labeling the data. We can transform the tuple we’re using into a data type with a name for the whole as well as names for the -parts, as shown in Listing 5-9: +parts, as shown in Listing 5-10: Filename: src/main.rs @@ -118,7 +118,7 @@ fn area(rectangle: &Rectangle) -> u32 { } ``` -Listing 5-9: Defining a `Rectangle` struct +Listing 5-10: Defining a `Rectangle` struct Here we’ve defined a struct and named it `Rectangle`. Inside the `{}` we defined the fields as `length` and `width`, both of which have type `u32`. Then @@ -143,7 +143,7 @@ and `1`—a win for clarity. It would be helpful to be able to print out an instance of the `Rectangle` while we’re debugging our program in order to see the values for all its -fields. Listing 5-10 uses the `println!` macro as we have been in earlier +fields. Listing 5-11 uses the `println!` macro as we have been in earlier chapters: Filename: src/main.rs @@ -161,7 +161,7 @@ fn main() { } ``` -Listing 5-10: Attempting to print a `Rectangle` +Listing 5-11: Attempting to print a `Rectangle` instance When we run this code, we get an error with this core message: @@ -209,7 +209,7 @@ crate, add `#[derive(Debug)]` or manually implement it Rust *does* include functionality to print out debugging information, but we have to explicitly opt-in to make that functionality available for our struct. To do that, we add the annotation `#[derive(Debug)]` just before the struct -definition, as shown in Listing 5-11: +definition, as shown in Listing 5-12: Filename: src/main.rs @@ -227,7 +227,7 @@ fn main() { } ``` -Listing5-11: Adding the annotation to derive the `Debug` +Listing 5-12: Adding the annotation to derive the `Debug` trait and printing the `Rectangle` instance using debug formatting Now when we run the program, we won’t get any errors and we’ll see the diff --git a/second-edition/src/ch05-03-method-syntax.md b/second-edition/src/ch05-03-method-syntax.md index b12b1f95e..6f3d02bc9 100644 --- a/second-edition/src/ch05-03-method-syntax.md +++ b/second-edition/src/ch05-03-method-syntax.md @@ -1,7 +1,7 @@ ## Method Syntax *Methods* are similar to functions: they’re declared with the `fn` keyword and -their name, they can have parameters and return values, and they contain some +their name, they can have parameters and a return value, and they contain some code that is run when they’re called from somewhere else. However, methods are different from functions in that they’re defined within the context of a struct (or an enum or a trait object, which we cover in Chapters 6 and 17, @@ -12,7 +12,7 @@ instance of the struct the method is being called on. Let’s change the `area` function that has a `Rectangle` instance as a parameter and instead make an `area` method defined on the `Rectangle` struct, as shown -in Listing 5-12: +in Listing 5-13: Filename: src/main.rs @@ -39,7 +39,7 @@ fn main() { } ``` -Listing 5-12: Defining an `area` method on the +Listing 5-13: Defining an `area` method on the `Rectangle` struct To define the function within the context of `Rectangle`, we start an `impl` @@ -124,7 +124,7 @@ Let’s practice using methods by implementing a second method on the `Rectangle struct. This time, we want an instance of `Rectangle` to take another instance of `Rectangle` and return `true` if the second `Rectangle` can fit completely within `self`; otherwise it should return `false`. That is, we want to be able -to write the program shown in Listing 5-13, once we’ve defined the `can_hold` +to write the program shown in Listing 5-14, once we’ve defined the `can_hold` method: Filename: src/main.rs @@ -140,7 +140,7 @@ fn main() { } ``` -Listing 5-13: Demonstration of using the as-yet-unwritten +Listing 5-14: Demonstration of using the as-yet-unwritten `can_hold` method And the expected output would look like the following, because both dimensions @@ -164,7 +164,7 @@ calling the `can_hold` method. The return value of `can_hold` will be a boolean, and the implementation will check whether the length and width of `self` are both greater than the length and width of the other `Rectangle`, respectively. Let’s add the new `can_hold` method to the `impl` block from -Listing 5-12, shown in Listing 5-14: +Listing 5-13, shown in Listing 5-15: Filename: src/main.rs @@ -186,10 +186,10 @@ impl Rectangle { } ``` -Listing 5-14: Implementing the `can_hold` method on +Listing 5-15: Implementing the `can_hold` method on `Rectangle` that takes another `Rectangle` instance as a parameter -When we run this code with the `main` function in Listing 5-13, we’ll get our +When we run this code with the `main` function in Listing 5-14, we’ll get our desired output. Methods can take multiple parameters that we add to the signature after the `self` parameter, and those parameters work just like parameters in functions. diff --git a/second-edition/src/ch06-02-match.md b/second-edition/src/ch06-02-match.md index 92c1df174..b7ce42ea7 100644 --- a/second-edition/src/ch06-02-match.md +++ b/second-edition/src/ch06-02-match.md @@ -27,7 +27,7 @@ enum Coin { Quarter, } -fn value_in_cents(coin: Coin) -> i32 { +fn value_in_cents(coin: Coin) -> u32 { match coin { Coin::Penny => 1, Coin::Nickel => 5, @@ -76,7 +76,7 @@ with a `Coin::Penny` but would still return the last value of the block, `1`: # Quarter, # } # -fn value_in_cents(coin: Coin) -> i32 { +fn value_in_cents(coin: Coin) -> u32 { match coin { Coin::Penny => { println!("Lucky penny!"); @@ -145,7 +145,7 @@ quarter’s state. Then we can use `state` in the code for that arm, like so: # Quarter(UsState), # } # -fn value_in_cents(coin: Coin) -> i32 { +fn value_in_cents(coin: Coin) -> u32 { match coin { Coin::Penny => 1, Coin::Nickel => 5, diff --git a/second-edition/src/ch08-02-strings.md b/second-edition/src/ch08-02-strings.md index a43d99aa5..e47c176e6 100644 --- a/second-edition/src/ch08-02-strings.md +++ b/second-edition/src/ch08-02-strings.md @@ -410,4 +410,4 @@ of strings than other programming languages do, but this will prevent you from having to handle errors involving non-ASCII characters later in your development lifecycle. -Let’s switch to something a bit less complex: hash map! +Let’s switch to something a bit less complex: hash maps! diff --git a/second-edition/src/ch15-05-interior-mutability.md b/second-edition/src/ch15-05-interior-mutability.md index 75e3e375d..a9ebf9f97 100644 --- a/second-edition/src/ch15-05-interior-mutability.md +++ b/second-edition/src/ch15-05-interior-mutability.md @@ -99,16 +99,16 @@ a is 5 a is 6 ``` -In `main`, we've created a new `RefCell` containing the value 5, and stored +In `main`, we've created a new `RefCell` containing the value 5, and stored in the variable `data`, declared without the `mut` keyword. We then call the `demo` function with an immutable reference to `data`: as far as `main` is concerned, `data` is immutable! In the `demo` function, we get an immutable reference to the value inside the -`RefCell` by calling the `borrow` method, and we call +`RefCell` by calling the `borrow` method, and we call `a_fn_that_immutably_borrows` with that immutable reference. More interestingly, we can get a *mutable* reference to the value inside the -`RefCell` with the `borrow_mut` method, and the function +`RefCell` with the `borrow_mut` method, and the function `a_fn_that_mutably_borrows` is allowed to change the value. We can see that the next time we call `a_fn_that_immutably_borrows` that prints out the value, it's 6 instead of 5. @@ -229,8 +229,8 @@ can create lists `b` and `c` that start differently but both refer to `a`, similarly to what we did in Listing 15-12. Once we have the lists in `shared_list`, `b`, and `c` created, then we add 10 -to the 5 in `value` by dereferencing the `Rc` and calling `borrow_mut` on -the `RefCell`. +to the 5 in `value` by dereferencing the `Rc` and calling `borrow_mut` on +the `RefCell`. When we print out `shared_list`, `b`, and `c`, we can see that they all have the modified value of 15: diff --git a/second-edition/src/ch17-03-oo-design-patterns.md b/second-edition/src/ch17-03-oo-design-patterns.md index 2e1fc8966..37c025eec 100644 --- a/second-edition/src/ch17-03-oo-design-patterns.md +++ b/second-edition/src/ch17-03-oo-design-patterns.md @@ -194,7 +194,7 @@ works as we intend. ### Requesting a Review of the Post Changes its State Next up is requesting a review of a post, which should change its state from -`Draft` to `PendingReview`. We want `post` to have a public method named +`Draft` to `PendingReview`. We want `Post` to have a public method named `request_review` that will take a mutable reference to `self`. Then we're going to call an internal `request_review` method on the state that we're holding, and this second `request_review` method will consume the current state and return a diff --git a/second-edition/src/ch19-02-advanced-lifetimes.md b/second-edition/src/ch19-02-advanced-lifetimes.md index 5ca16d5ec..14b74b0e6 100644 --- a/second-edition/src/ch19-02-advanced-lifetimes.md +++ b/second-edition/src/ch19-02-advanced-lifetimes.md @@ -277,57 +277,56 @@ something you have a reference to. ### Lifetime Bounds In Chapter 10, we discussed how to use trait bounds on generic types. We can -also add lifetime parameters as constraints on generic types. For example, -let's say we wanted to make a wrapper over references. Remember `RefCell` -from Chapter 15? This is how the `borrow` and `borrow_mut` methods work; they -return wrappers over references in order to keep track of the borrowing rules -at runtime. The struct definition, without lifetime parameters for now, would -look like Listing 19-16: +also add lifetime parameters as constraints on generic types, which are called +*lifetime bounds*. For example, consider a type that is a wrapper over +references. Recall the `RefCell` type from Chapter 15: its `borrow` and +`borrow_mut` methods return the types `Ref` and `RefMut`, respectively. These +types are wrappers over references that keep track of the borrowing rules at +runtime. The definition of the `Ref` struct is shown in Listing 19-16, without +lifetime bounds for now: ```rust,ignore -struct Ref(&T); +struct Ref<'a, T>(&'a T); ``` Listing 19-16: Defining a struct to wrap a reference to a -generic type; without lifetime parameters to start +generic type; without lifetime bounds to start -However, using no lifetime bounds at all gives an error because Rust doesn't -know how long the generic type `T` will live: +Without constraining the lifetime `'a` in relation to the generic parameter +`T`, we get an error because Rust doesn't know how long the generic type `T` +will live: ```text error[E0309]: the parameter type `T` may not live long enough - --> :2:19 + --> :1:19 | -2 | struct Ref<'a, T>(&'a T); +1 | struct Ref<'a, T>(&'a T); | ^^^^^^ | = help: consider adding an explicit lifetime bound `T: 'a`... note: ...so that the reference type `&'a T` does not outlive the data it points at - --> :2:19 + --> :1:19 | -2 | struct Ref<'a, T>(&'a T); +1 | struct Ref<'a, T>(&'a T); | ^^^^^^ ``` -This is the same error that we'd get if we filled in `T` with a concrete type, -like `struct Ref(&i32)`; all references in struct definitions need a lifetime -parameter. However, because we have a generic type parameter, we can't add a -lifetime parameter in the same way. Defining `Ref` as `struct Ref<'a>(&'a T)` -will result in an error because Rust can't determine that `T` lives long -enough. Since `T` can be any type, `T` could itself be a reference or it could -be a type that holds one or more references, each of which have their own -lifetimes. +Since `T` can be any type, `T` could itself be a reference or a type that holds +one or more references, each of which could have their own lifetimes. Rust +can't be sure `T` will live as long as `'a`. -Rust helpfully gave us good advice on how to specify the lifetime parameter in +Fortunately, Rust gave us helpful advice on how to specify the lifetime bound in this case: ```text consider adding an explicit lifetime bound `T: 'a` so that the reference type -`&'a T` does not outlive the data it points to. +`&'a T` does not outlive the data it points at. ``` -The code in Listing 19-17 works because `T: 'a` syntax specifies that `T` can -be any type, but if it contains any references, `T` must live as long as `'a`: +Listing 19-17 shows how to apply this advice by specifying the lifetime bound +when we declare the generic type `T`. This code now compiles because the `T: +'a` syntax specifies that `T` can be any type, but if it contains any +references, the references must live at least as long as `'a`: ```rust struct Ref<'a, T: 'a>(&'a T); @@ -336,9 +335,10 @@ struct Ref<'a, T: 'a>(&'a T); Listing 19-17: Adding lifetime bounds on `T` to specify that any references in `T` live at least as long as `'a` -We could choose to solve this in a different way as shown in Listing 19-18 by -bounding `T` on `'static`. This means if `T` contains any references, they must -have the `'static` lifetime: +We could choose to solve this in a different way, shown in the definition of a +`StaticRef` struct in Listing 19-18, by adding the `'static` lifetime bound on +`T`. This means if `T` contains any references, they must have the `'static` +lifetime: ```rust struct StaticRef(&'static T); @@ -348,7 +348,7 @@ struct StaticRef(&'static T); to constrain `T` to types that have only `'static` references or no references -Types with no references count as `T: 'static`. Because `'static` means the +Types without any references count as `T: 'static`. Because `'static` means the reference must live as long as the entire program, a type that contains no references meets the criteria of all references living as long as the entire program (since there are no references). Think of it this way: if the borrow diff --git a/second-edition/src/ch19-04-advanced-types.md b/second-edition/src/ch19-04-advanced-types.md index c03042b3d..d6f76e869 100644 --- a/second-edition/src/ch19-04-advanced-types.md +++ b/second-edition/src/ch19-04-advanced-types.md @@ -163,10 +163,10 @@ another `Result`, which means we can use any methods that work on ### The Never Type, `!`, that Never Returns -Rust has a special type named `!`. In type theory lingo, it's called the -*bottom type*, but we prefer to call it the *never type*. The name describes -what it does: it stands in the place of the return type when a function will -never return. For example: +Rust has a special type named `!`. In type theory lingo, it's called the *empty +type*, because it has no values. We prefer to call it the *never type*. The name +describes what it does: it stands in the place of the return type when a +function will never return. For example: ```rust,ignore fn bar() -> ! { diff --git a/second-edition/theme/index.hbs b/second-edition/theme/index.hbs index 7635dcdce..ea382b0aa 100644 --- a/second-edition/theme/index.hbs +++ b/second-edition/theme/index.hbs @@ -159,6 +159,7 @@ {{{livereload}}} +