diff --git a/src/ch10-00-generics.md b/src/ch10-00-generics.md index 56ceee20dc..2e68384e11 100644 --- a/src/ch10-00-generics.md +++ b/src/ch10-00-generics.md @@ -42,14 +42,13 @@ duplicated code that can use generics. We’ll begin with the short program in Listing 10-1 that finds the largest number in a list. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-01/src/main.rs:here}} ``` -Listing 10-1: Finding the largest number in a list of -numbers + We store a list of integers in the variable `number_list` and place a reference to the first number in the list in a variable named `largest`. We then iterate @@ -64,14 +63,13 @@ We’ve now been tasked with finding the largest number in two different lists o numbers. To do so, we can choose to duplicate the code in Listing 10-1 and use the same logic at two different places in the program, as shown in Listing 10-2. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-02/src/main.rs}} ``` -Listing 10-2: Code to find the largest number in *two* -lists of numbers + Although this code works, duplicating code is tedious and error prone. We also have to remember to update the code in multiple places when we want to change @@ -87,14 +85,13 @@ function named `largest`. Then we call the function to find the largest number in the two lists from Listing 10-2. We could also use the function on any other list of `i32` values we might have in the future. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-03/src/main.rs:here}} ``` -Listing 10-3: Abstracted code to find the largest number -in two lists + The `largest` function has a parameter called `list`, which represents any concrete slice of `i32` values we might pass into the function. As a result, diff --git a/src/ch10-01-syntax.md b/src/ch10-01-syntax.md index 0b71c04c5b..2a22baf581 100644 --- a/src/ch10-01-syntax.md +++ b/src/ch10-01-syntax.md @@ -16,14 +16,13 @@ Continuing with our `largest` function, Listing 10-4 shows two functions that both find the largest value in a slice. We’ll then combine these into a single function that uses generics. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-04/src/main.rs:here}} ``` -Listing 10-4: Two functions that differ only in their -names and in the types in their signatures + The `largest_i32` function is the one we extracted in Listing 10-3 that finds the largest `i32` in a slice. The `largest_char` function finds the largest @@ -58,14 +57,13 @@ data type in its signature. The listing also shows how we can call the function with either a slice of `i32` values or `char` values. Note that this code won’t compile yet, but we’ll fix it later in this chapter. -Filename: src/main.rs + ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/src/main.rs}} ``` -Listing 10-5: The `largest` function using generic type -parameters; this doesn’t compile yet + If we compile this code right now, we’ll get this error: @@ -90,14 +88,13 @@ We can also define structs to use a generic type parameter in one or more fields using the `<>` syntax. Listing 10-6 defines a `Point` struct to hold `x` and `y` coordinate values of any type. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-06/src/main.rs}} ``` -Listing 10-6: A `Point` struct that holds `x` and `y` -values of type `T` + The syntax for using generics in struct definitions is similar to that used in function definitions. First we declare the name of the type parameter inside @@ -111,14 +108,13 @@ the fields `x` and `y` are *both* that same type, whatever that type may be. If we create an instance of a `Point` that has values of different types, as in Listing 10-7, our code won’t compile. -Filename: src/main.rs + ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-07/src/main.rs}} ``` -Listing 10-7: The fields `x` and `y` must be the same -type because both have the same generic data type `T`. + In this example, when we assign the integer value `5` to `x`, we let the compiler know that the generic type `T` will be an integer for this instance of @@ -134,14 +130,13 @@ different types, we can use multiple generic type parameters. For example, in Listing 10-8, we change the definition of `Point` to be generic over types `T` and `U` where `x` is of type `T` and `y` is of type `U`. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-08/src/main.rs}} ``` -Listing 10-8: A `Point` generic over two types so -that `x` and `y` can be values of different types + Now all the instances of `Point` shown are allowed! You can use as many generic type parameters in a definition as you want, but using more than a few makes @@ -198,15 +193,13 @@ We can implement methods on structs and enums (as we did in Chapter 5) and use generic types in their definitions too. Listing 10-9 shows the `Point` struct we defined in Listing 10-6 with a method named `x` implemented on it. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-09/src/main.rs}} ``` -Listing 10-9: Implementing a method named `x` on the -`Point` struct that will return a reference to the `x` field of type -`T` + Here, we’ve defined a method named `x` on `Point` that returns a reference to the data in the field `x`. @@ -226,14 +219,13 @@ type. We could, for example, implement methods only on `Point` instances rather than on `Point` instances with any generic type. In Listing 10-10 we use the concrete type `f32`, meaning we don’t declare any types after `impl`. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-10/src/main.rs:here}} ``` -Listing 10-10: An `impl` block that only applies to a -struct with a particular concrete type for the generic type parameter `T` + This code means the type `Point` will have a `distance_from_origin` method; other instances of `Point` where `T` is not of type `f32` will not @@ -248,14 +240,13 @@ signature to make the example clearer. The method creates a new `Point` instance with the `x` value from the `self` `Point` (of type `X1`) and the `y` value from the passed-in `Point` (of type `Y2`). -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-11/src/main.rs}} ``` -Listing 10-11: A method that uses generic types different -from its struct’s definition + In `main`, we’ve defined a `Point` that has an `i32` for `x` (with value `5`) and an `f64` for `y` (with value `10.4`). The `p2` variable is a `Point` struct @@ -304,7 +295,7 @@ definition with the specific ones. The monomorphized version of the code looks similar to the following (the compiler uses different names than what we’re using here for illustration): -Filename: src/main.rs + ```rust enum Option_i32 { @@ -323,6 +314,8 @@ fn main() { } ``` + + The generic `Option` is replaced with the specific definitions created by the compiler. Because Rust compiles generic code into code that specifies the type in each instance, we pay no runtime cost for using generics. When the code diff --git a/src/ch10-02-traits.md b/src/ch10-02-traits.md index 53e9b8115c..cfd4201066 100644 --- a/src/ch10-02-traits.md +++ b/src/ch10-02-traits.md @@ -27,14 +27,13 @@ instance. To do this, we need a summary from each type, and we’ll request that summary by calling a `summarize` method on an instance. Listing 10-12 shows the definition of a public `Summary` trait that expresses this behavior. -Filename: src/lib.rs + ```rust,noplayground {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/src/lib.rs}} ``` -Listing 10-12: A `Summary` trait that consists of the -behavior provided by a `summarize` method + Here, we declare a trait using the `trait` keyword and then the trait’s name, which is `Summary` in this case. We also declare the trait as `pub` so that @@ -62,14 +61,13 @@ the headline, the author, and the location to create the return value of followed by the entire text of the tweet, assuming that the tweet content is already limited to 280 characters. -Filename: src/lib.rs + ```rust,noplayground {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/src/lib.rs:here}} ``` -Listing 10-13: Implementing the `Summary` trait on the -`NewsArticle` and `Tweet` types + Implementing a trait on a type is similar to implementing regular methods. The difference is that after `impl`, we put the trait name we want to implement, @@ -124,14 +122,13 @@ In Listing 10-14, we specify a default string for the `summarize` method of the `Summary` trait instead of only defining the method signature, as we did in Listing 10-12. -Filename: src/lib.rs + ```rust,noplayground {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/src/lib.rs:here}} ``` -Listing 10-14: Defining a `Summary` trait with a default -implementation of the `summarize` method + To use a default implementation to summarize instances of `NewsArticle`, we specify an empty `impl` block with `impl Summary for NewsArticle {}`. @@ -339,14 +336,13 @@ is a type alias for the type of the `impl` block, which in this case is `cmp_display` method if its inner type `T` implements the `PartialOrd` trait that enables comparison *and* the `Display` trait that enables printing. -Filename: src/lib.rs + ```rust,noplayground {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-15/src/lib.rs}} ``` -Listing 10-15: Conditionally implementing methods on a -generic type depending on trait bounds + We can also conditionally implement a trait for any type that implements another trait. Implementations of a trait on any type that satisfies the trait diff --git a/src/ch10-03-lifetime-syntax.md b/src/ch10-03-lifetime-syntax.md index d327e512b9..1657a1979b 100644 --- a/src/ch10-03-lifetime-syntax.md +++ b/src/ch10-03-lifetime-syntax.md @@ -26,12 +26,13 @@ program to reference data other than the data it’s intended to reference. Consider the program in Listing 10-16, which has an outer scope and an inner scope. ++ ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/src/main.rs}} ``` -Listing 10-16: An attempt to use a reference whose value -has gone out of scope + > Note: The examples in Listing 10-16, 10-17, and 10-23 declare variables > without giving them an initial value, so the variable name exists in the outer @@ -65,12 +66,13 @@ The Rust compiler has a *borrow checker* that compares scopes to determine whether all borrows are valid. Listing 10-17 shows the same code as Listing 10-16 but with annotations showing the lifetimes of the variables. ++ ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/src/main.rs}} ``` -Listing 10-17: Annotations of the lifetimes of `r` and -`x`, named `'a` and `'b`, respectively + Here, we’ve annotated the lifetime of `r` with `'a` and the lifetime of `x` with `'b`. As you can see, the inner `'b` block is much smaller than the outer @@ -82,12 +84,13 @@ with a lifetime of `'b`. The program is rejected because `'b` is shorter than Listing 10-18 fixes the code so it doesn’t have a dangling reference and it compiles without any errors. ++ ```rust {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-18/src/main.rs}} ``` -Listing 10-18: A valid reference because the data has a -longer lifetime than the reference + Here, `x` has the lifetime `'b`, which in this case is larger than `'a`. This means `r` can reference `x` because Rust knows that the reference in `r` will @@ -104,14 +107,13 @@ function will take two string slices and return a single string slice. After we’ve implemented the `longest` function, the code in Listing 10-19 should print `The longest string is abcd`. -Filename: src/main.rs + ```rust,ignore {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/src/main.rs}} ``` -Listing 10-19: A `main` function that calls the `longest` -function to find the longer of two string slices + Note that we want the function to take string slices, which are references, rather than strings, because we don’t want the `longest` function to take @@ -123,15 +125,13 @@ ones we want. If we try to implement the `longest` function as shown in Listing 10-20, it won’t compile. -Filename: src/main.rs + ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/src/main.rs:here}} ``` -Listing 10-20: An implementation of the `longest` -function that returns the longer of two string slices but does not yet -compile + Instead, we get the following error that talks about lifetimes: @@ -197,15 +197,13 @@ relationship between lifetimes of the parameters and the return value. We’ll name the lifetime `'a` and then add it to each reference, as shown in Listing 10-21. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/src/main.rs:here}} ``` -Listing 10-21: The `longest` function definition -specifying that all the references in the signature must have the same lifetime -`'a` + This code should compile and produce the result we want when we use it with the `main` function in Listing 10-19. @@ -249,14 +247,13 @@ Let’s look at how the lifetime annotations restrict the `longest` function by passing in references that have different concrete lifetimes. Listing 10-22 is a straightforward example. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-22/src/main.rs:here}} ``` -Listing 10-22: Using the `longest` function with -references to `String` values that have different concrete lifetimes + In this example, `string1` is valid until the end of the outer scope, `string2` is valid until the end of the inner scope, and `result` references something @@ -272,14 +269,13 @@ assignment of the value to the `result` variable inside the scope with inner scope, after the inner scope has ended. The code in Listing 10-23 will not compile. -Filename: src/main.rs + ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/src/main.rs:here}} ``` -Listing 10-23: Attempting to use `result` after `string2` -has gone out of scope + When we try to compile this code, we get this error: @@ -314,12 +310,14 @@ function is doing. For example, if we changed the implementation of the string slice, we wouldn’t need to specify a lifetime on the `y` parameter. The following code will compile: -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-08-only-one-reference-with-lifetime/src/main.rs:here}} ``` + + We’ve specified a lifetime parameter `'a` for the parameter `x` and the return type, but not for the parameter `y`, because the lifetime of `y` does not have any relationship with the lifetime of `x` or the return value. @@ -332,12 +330,14 @@ reference because the value will go out of scope at the end of the function. Consider this attempted implementation of the `longest` function that won’t compile: -Filename: src/main.rs + ```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/src/main.rs:here}} ``` + + Here, even though we’ve specified a lifetime parameter `'a` for the return type, this implementation will fail to compile because the return value lifetime is not related to the lifetime of the parameters at all. Here is the @@ -367,14 +367,13 @@ to hold references, but in that case we would need to add a lifetime annotation on every reference in the struct’s definition. Listing 10-24 has a struct named `ImportantExcerpt` that holds a string slice. -Filename: src/main.rs + ```rust {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/src/main.rs}} ``` -Listing 10-24: A struct that holds a reference, requiring -a lifetime annotation + This struct has the single field `part` that holds a string slice, which is a reference. As with generic data types, we declare the name of the generic @@ -397,15 +396,13 @@ lifetime parameters for functions or structs that use references. However, we had a function in Listing 4-9, shown again in Listing 10-25, that compiled without lifetime annotations. -Filename: src/lib.rs + ```rust {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/src/main.rs:here}} ``` -Listing 10-25: A function we defined in Listing 4-9 that -compiled without lifetime annotations, even though the parameter and return -type are references + The reason this function compiles without lifetime annotations is historical: in early versions (pre-1.0) of Rust, this code wouldn’t have compiled because