Skip to content

Commit

Permalink
Use <Listing> for Chapter 15
Browse files Browse the repository at this point in the history
This restores the work originally done in #3956, which had to be dropped
from that PR because this chapter was blocked on XML handling, which was
resolved in #3975.

Co-authored-by: Bryan Zierk <[email protected]>
  • Loading branch information
chriskrycho and bzierk committed Oct 15, 2024
1 parent ec6b1b4 commit d8a10b8
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 83 deletions.
25 changes: 11 additions & 14 deletions src/ch15-01-box.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,13 @@ syntax and how to interact with values stored within a `Box<T>`.

Listing 15-1 shows how to use a box to store an `i32` value on the heap:

<span class="filename">Filename: src/main.rs</span>
<Listing number="15-1" file-name="src/main.rs" caption="Storing an `i32` value on the heap using a box">

```rust
{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-01/src/main.rs}}
```

<span class="caption">Listing 15-1: Storing an `i32` value on the heap using a
box</span>
</Listing>

We define the variable `b` to have the value of a `Box` that points to the
value `5`, which is allocated on the heap. This program will print `b = 5`; in
Expand Down Expand Up @@ -106,14 +105,13 @@ Listing 15-2 contains an enum definition for a cons list. Note that this code
won’t compile yet because the `List` type doesn’t have a known size, which
we’ll demonstrate.

<span class="filename">Filename: src/main.rs</span>
<Listing number="15-2" file-name="src/main.rs" caption="The first attempt at defining an enum to represent a cons list data structure of `i32` values">

```rust,ignore,does_not_compile
{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-02/src/main.rs:here}}
```

<span class="caption">Listing 15-2: The first attempt at defining an enum to
represent a cons list data structure of `i32` values</span>
</Listing>

> Note: We’re implementing a cons list that holds only `i32` values for the
> purposes of this example. We could have implemented it using generics, as we
Expand All @@ -123,14 +121,13 @@ represent a cons list data structure of `i32` values</span>
Using the `List` type to store the list `1, 2, 3` would look like the code in
Listing 15-3:

<span class="filename">Filename: src/main.rs</span>
<Listing number="15-3" file-name="src/main.rs" caption="Using the `List` enum to store the list `1, 2, 3`">

```rust,ignore,does_not_compile
{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-03/src/main.rs:here}}
```

<span class="caption">Listing 15-3: Using the `List` enum to store the list `1,
2, 3`</span>
</Listing>

The first `Cons` value holds `1` and another `List` value. This `List` value is
another `Cons` value that holds `2` and another `List` value. This `List` value
Expand All @@ -140,12 +137,13 @@ is one more `Cons` value that holds `3` and a `List` value, which is finally
If we try to compile the code in Listing 15-3, we get the error shown in
Listing 15-4:

<Listing number="15-4" file-name="output.txt" caption="The error we get when attempting to define a recursive enum">

```console
{{#include ../listings/ch15-smart-pointers/listing-15-03/output.txt}}
```

<span class="caption">Listing 15-4: The error we get when attempting to define
a recursive enum</span>
</Listing>

The error shows this type “has infinite size.” The reason is that we’ve defined
`List` with a variant that is recursive: it holds another value of itself
Expand Down Expand Up @@ -215,14 +213,13 @@ rather than inside one another.
We can change the definition of the `List` enum in Listing 15-2 and the usage
of the `List` in Listing 15-3 to the code in Listing 15-5, which will compile:

<span class="filename">Filename: src/main.rs</span>
<Listing number="15-5" file-name="src/main.rs" caption="Definition of `List` that uses `Box<T>` in order to have a known size">

```rust
{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-05/src/main.rs}}
```

<span class="caption">Listing 15-5: Definition of `List` that uses `Box<T>` in
order to have a known size</span>
</Listing>

The `Cons` variant needs the size of an `i32` plus the space to store the
box’s pointer data. The `Nil` variant stores no values, so it needs less space
Expand Down
38 changes: 16 additions & 22 deletions src/ch15-02-deref.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,13 @@ as an arrow to a value stored somewhere else. In Listing 15-6, we create a
reference to an `i32` value and then use the dereference operator to follow the
reference to the value:

<span class="filename">Filename: src/main.rs</span>
<Listing number="15-6" file-name="src/main.rs" caption="Using the dereference operator to follow a reference to an `i32` value">

```rust
{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-06/src/main.rs}}
```

<span class="caption">Listing 15-6: Using the dereference operator to follow a
reference to an `i32` value</span>
</Listing>

The variable `x` holds an `i32` value `5`. We set `y` equal to a reference to
`x`. We can assert that `x` is equal to `5`. However, if we want to make an
Expand All @@ -63,14 +62,13 @@ reference; the dereference operator used on the `Box<T>` in Listing 15-7
functions in the same way as the dereference operator used on the reference in
Listing 15-6:

<span class="filename">Filename: src/main.rs</span>
<Listing number="15-7" file-name="src/main.rs" caption="Using the dereference operator on a `Box<i32>`">

```rust
{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-07/src/main.rs}}
```

<span class="caption">Listing 15-7: Using the dereference operator on a
`Box<i32>`</span>
</Listing>

The main difference between Listing 15-7 and Listing 15-6 is that here we set
`y` to be an instance of a `Box<T>` pointing to a copied value of `x` rather
Expand All @@ -91,13 +89,13 @@ The `Box<T>` type is ultimately defined as a tuple struct with one element, so
Listing 15-8 defines a `MyBox<T>` type in the same way. We’ll also define a
`new` function to match the `new` function defined on `Box<T>`.

<span class="filename">Filename: src/main.rs</span>
<Listing number="15-8" file-name="src/main.rs" caption="Defining a `MyBox<T>` type">

```rust
{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-08/src/main.rs:here}}
```

<span class="caption">Listing 15-8: Defining a `MyBox<T>` type</span>
</Listing>

We define a struct named `MyBox` and declare a generic parameter `T`, because
we want our type to hold values of any type. The `MyBox` type is a tuple struct
Expand All @@ -109,14 +107,13 @@ changing it to use the `MyBox<T>` type we’ve defined instead of `Box<T>`. The
code in Listing 15-9 won’t compile because Rust doesn’t know how to dereference
`MyBox`.

<span class="filename">Filename: src/main.rs</span>
<Listing number="15-9" file-name="src/main.rs" caption="Attempting to use `MyBox<T>` in the same way we used references and `Box<T>`">

```rust,ignore,does_not_compile
{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-09/src/main.rs:here}}
```

<span class="caption">Listing 15-9: Attempting to use `MyBox<T>` in the same
way we used references and `Box<T>`</span>
</Listing>

Here’s the resulting compilation error:

Expand All @@ -137,13 +134,13 @@ by the standard library, requires us to implement one method named `deref` that
borrows `self` and returns a reference to the inner data. Listing 15-10
contains an implementation of `Deref` to add to the definition of `MyBox`:

<span class="filename">Filename: src/main.rs</span>
<Listing number="15-10" file-name="src/main.rs" caption="Implementing `Deref` on `MyBox<T>`">

```rust
{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-10/src/main.rs:here}}
```

<span class="caption">Listing 15-10: Implementing `Deref` on `MyBox<T>`</span>
</Listing>

The `type Target = T;` syntax defines an associated type for the `Deref`
trait to use. Associated types are a slightly different way of declaring a
Expand Down Expand Up @@ -210,27 +207,25 @@ Listing 15-8 as well as the implementation of `Deref` that we added in Listing
15-10. Listing 15-11 shows the definition of a function that has a string slice
parameter:

<span class="filename">Filename: src/main.rs</span>
<Listing number="15-11" file-name="src/main.rs" caption="A `hello` function that has the parameter `name` of type `&str`">

```rust
{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-11/src/main.rs:here}}
```

<span class="caption">Listing 15-11: A `hello` function that has the parameter
`name` of type `&str`</span>
</Listing>

We can call the `hello` function with a string slice as an argument, such as
`hello("Rust");` for example. Deref coercion makes it possible to call `hello`
with a reference to a value of type `MyBox<String>`, as shown in Listing 15-12:

<span class="filename">Filename: src/main.rs</span>
<Listing number="15-12" file-name="src/main.rs" caption="Calling `hello` with a reference to a `MyBox<String>` value, which works because of deref coercion">

```rust
{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-12/src/main.rs:here}}
```

<span class="caption">Listing 15-12: Calling `hello` with a reference to a
`MyBox<String>` value, which works because of deref coercion</span>
</Listing>

Here we’re calling the `hello` function with the argument `&m`, which is a
reference to a `MyBox<String>` value. Because we implemented the `Deref` trait
Expand All @@ -244,14 +239,13 @@ If Rust didn’t implement deref coercion, we would have to write the code in
Listing 15-13 instead of the code in Listing 15-12 to call `hello` with a value
of type `&MyBox<String>`.

<span class="filename">Filename: src/main.rs</span>
<Listing number="15-13" file-name="src/main.rs" caption="The code we would have to write if Rust didn’t have deref coercion">

```rust
{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-13/src/main.rs:here}}
```

<span class="caption">Listing 15-13: The code we would have to write if Rust
didn’t have deref coercion</span>
</Listing>

The `(*m)` dereferences the `MyBox<String>` into a `String`. Then the `&` and
`[..]` take a string slice of the `String` that is equal to the whole string to
Expand Down
15 changes: 6 additions & 9 deletions src/ch15-03-drop.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,13 @@ Listing 15-14 shows a `CustomSmartPointer` struct whose only custom
functionality is that it will print `Dropping CustomSmartPointer!` when the
instance goes out of scope, to show when Rust runs the `drop` function.

<span class="filename">Filename: src/main.rs</span>
<Listing number="15-14" file-name="src/main.rs" caption="A `CustomSmartPointer` struct that implements the `Drop` trait where we would put our cleanup code">

```rust
{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-14/src/main.rs}}
```

<span class="caption">Listing 15-14: A `CustomSmartPointer` struct that
implements the `Drop` trait where we would put our cleanup code</span>
</Listing>

The `Drop` trait is included in the prelude, so we don’t need to bring it into
scope. We implement the `Drop` trait on `CustomSmartPointer` and provide an
Expand Down Expand Up @@ -79,14 +78,13 @@ If we try to call the `Drop` trait’s `drop` method manually by modifying the
`main` function from Listing 15-14, as shown in Listing 15-15, we’ll get a
compiler error:

<span class="filename">Filename: src/main.rs</span>
<Listing number="15-15" file-name="src/main.rs" caption="Attempting to call the `drop` method from the `Drop` trait manually to clean up early">

```rust,ignore,does_not_compile
{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-15/src/main.rs:here}}
```

<span class="caption">Listing 15-15: Attempting to call the `drop` method from
the `Drop` trait manually to clean up early</span>
</Listing>

When we try to compile this code, we’ll get this error:

Expand Down Expand Up @@ -114,14 +112,13 @@ trait. We call it by passing as an argument the value we want to force drop.
The function is in the prelude, so we can modify `main` in Listing 15-15 to
call the `drop` function, as shown in Listing 15-16:

<span class="filename">Filename: src/main.rs</span>
<Listing number="15-16" file-name="src/main.rs" caption="Calling `std::mem::drop` to explicitly drop a value before it goes out of scope">

```rust
{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-16/src/main.rs:here}}
```

<span class="caption">Listing 15-16: Calling `std::mem::drop` to explicitly
drop a value before it goes out of scope</span>
</Listing>

Running this code will print the following:

Expand Down
14 changes: 6 additions & 8 deletions src/ch15-04-rc.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,13 @@ words, both lists will share the first list containing 5 and 10.
Trying to implement this scenario using our definition of `List` with `Box<T>`
won’t work, as shown in Listing 15-17:

<span class="filename">Filename: src/main.rs</span>
<Listing number="15-17" file-name="src/main.rs" caption="Demonstrating we’re not allowed to have two lists using `Box<T>` that try to share ownership of a third list">

```rust,ignore,does_not_compile
{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-17/src/main.rs}}
```

<span class="caption">Listing 15-17: Demonstrating we’re not allowed to have
two lists using `Box<T>` that try to share ownership of a third list</span>
</Listing>

When we compile this code, we get this error:

Expand Down Expand Up @@ -84,14 +83,13 @@ we call `Rc::clone`, the reference count to the data within the `Rc<List>` will
increase, and the data won’t be cleaned up unless there are zero references to
it.

<span class="filename">Filename: src/main.rs</span>
<Listing number="15-18" file-name="src/main.rs" caption="A definition of `List` that uses `Rc<T>`">

```rust
{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-18/src/main.rs}}
```

<span class="caption">Listing 15-18: A definition of `List` that uses
`Rc<T>`</span>
</Listing>

We need to add a `use` statement to bring `Rc<T>` into scope because it’s not
in the prelude. In `main`, we create the list holding 5 and 10 and store it in
Expand All @@ -118,13 +116,13 @@ counts changing as we create and drop references to the `Rc<List>` in `a`.
In Listing 15-19, we’ll change `main` so it has an inner scope around list `c`;
then we can see how the reference count changes when `c` goes out of scope.

<span class="filename">Filename: src/main.rs</span>
<Listing number="15-19" file-name="src/main.rs" caption="Printing the reference count">

```rust
{{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-19/src/main.rs:here}}
```

<span class="caption">Listing 15-19: Printing the reference count</span>
</Listing>

At each point in the program where the reference count changes, we print the
reference count, which we get by calling the `Rc::strong_count` function. This
Expand Down
Loading

0 comments on commit d8a10b8

Please sign in to comment.