The Rust Programming Language › Customizing Builds with Release Profiles

In Rust, _release profiles_ are predefined, customizable profiles with
different configurations that allow a programmer to have more control over
various options for compiling code. Each profile is configured independently of
the others.
Cargo has two main profiles: the `dev` profile Cargo uses when you run `cargo
build`, and the `release` profile Cargo uses when you run `cargo build
--release`. The `dev` profile is defined with good defaults for development,
and the `release` profile has good defaults for release builds.
These profile names might be familiar from the output of your builds:
```console
$ cargo build
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
$ cargo build --release
    Finished `release` profile [optimized] target(s) in 0.32s
```
The `dev` and `release` are these different profiles used by the compiler.
Cargo has default settings for each of the profiles that apply when you haven't
explicitly added any `[profile.*]` sections in the project’s _Cargo.toml_ file.
By adding `[profile.*]` sections for any profile you want to customize, you
override any subset of the default settings. For example, here are the default
values for the `opt-level` setting for the `dev` and `release` profiles:
Filename: Cargo.toml
```toml
[profile.dev]
opt-level = 0

[profile.release]
opt-level = 3
```


The Rust Programming Language › Customizing Builds with Release Profiles

The `opt-level` setting controls the number of optimizations Rust will apply to
your code, with a range of 0 to 3. Applying more optimizations extends
compiling time, so if you’re in development and compiling your code often,
you’ll want fewer optimizations to compile faster even if the resultant code
runs slower. The default `opt-level` for `dev` is therefore `0`. When you’re
ready to release your code, it’s best to spend more time compiling. You’ll only
compile in release mode once, but you’ll run the compiled program many times,
so release mode trades longer compile time for code that runs faster. That is
why the default `opt-level` for the `release` profile is `3`.
You can override a default setting by adding a different value for it in
_Cargo.toml_. For example, if we want to use optimization level 1 in the
development profile, we can add these two lines to our project’s _Cargo.toml_
file:
Filename: Cargo.toml
```toml
[profile.dev]
opt-level = 1
```
This code overrides the default setting of `0`. Now when we run `cargo build`,
Cargo will use the defaults for the `dev` profile plus our customization to
`opt-level`. Because we set `opt-level` to `1`, Cargo will apply more
optimizations than the default, but not as many as in a release build.
For the full list of configuration options and defaults for each profile, see
Cargo’s documentation.


The Rust Programming Language › Publishing a Crate to Crates.io

We’ve used packages from crates.io as
dependencies of our project, but you can also share your code with other people
by publishing your own packages. The crate registry at
crates.io distributes the source code of
your packages, so it primarily hosts code that is open source.
Rust and Cargo have features that make your published package easier for people
to find and use. We’ll talk about some of these features next and then explain
how to publish a package.


The Rust Programming Language › Publishing a Crate to Crates.io › Making Useful Documentation Comments

Accurately documenting your packages will help other users know how and when to
use them, so it’s worth investing the time to write documentation. In Chapter
3, we discussed how to comment Rust code using two slashes, `//`. Rust also has
a particular kind of comment for documentation, known conveniently as a
_documentation comment_, that will generate HTML documentation. The HTML
displays the contents of documentation comments for public API items intended
for programmers interested in knowing how to _use_ your crate as opposed to how
your crate is _implemented_.
Documentation comments use three slashes, `///`, instead of two and support
Markdown notation for formatting the text. Place documentation comments just
before the item they’re documenting. Listing 14-1 shows documentation comments
for an `add_one` function in a crate named `my_crate`.
Listing 14-1: A documentation comment for a function (src/lib.rs)
```rust,ignore
/// Adds one to the number given.
///
/// # Examples
///
/// ```
/// let arg = 5;
/// let answer = my_crate::add_one(arg);
///
/// assert_eq!(6, answer);
/// ```
pub fn add_one(x: i32) -> i32 {
    x + 1
}
```
Here, we give a description of what the `add_one` function does, start a
section with the heading `Examples`, and then provide code that demonstrates
how to use the `add_one` function. We can generate the HTML documentation from
this documentation comment by running `cargo doc`. This command runs the
`rustdoc` tool distributed with Rust and puts the generated HTML documentation
in the _target/doc_ directory.

Publishing a Crate to Crates.io
Making Useful Documentation Comments


The Rust Programming Language › Publishing a Crate to Crates.io › Making Useful Documentation Comments › Documentation Comments as Tests

For convenience, running `cargo doc --open` will build the HTML for your
current crate’s documentation (as well as the documentation for all of your
crate’s dependencies) and open the result in a web browser. Navigate to the
`add_one` function and you’ll see how the text in the documentation comments is
rendered, as shown in Figure 14-1.
<img alt="Rendered HTML documentation for the `add_one` function of `my_crate`" src="img/trpl14-01.png" class="center" />
Figure 14-1: The HTML documentation for the `add_one`
function
We used the `# Examples` Markdown heading in Listing 14-1 to create a section
in the HTML with the title “Examples.” Here are some other sections that crate
authors commonly use in their documentation:
- **Panics**: These are the scenarios in which the function being documented
  could panic. Callers of the function who don’t want their programs to panic
  should make sure they don’t call the function in these situations.
- **Errors**: If the function returns a `Result`, describing the kinds of
  errors that might occur and what conditions might cause those errors to be
  returned can be helpful to callers so that they can write code to handle the
  different kinds of errors in different ways.
- **Safety**: If the function is `unsafe` to call (we discuss unsafety in
  Chapter 20), there should be a section explaining why the function is unsafe
  and covering the invariants that the function expects callers to uphold.
Most documentation comments don’t need all of these sections, but this is a
good checklist to remind you of the aspects of your code users will be
interested in knowing about.

Publishing a Crate to Crates.io
Making Useful Documentation Comments
Documentation Comments as Tests


The Rust Programming Language › Publishing a Crate to Crates.io › Making Useful Documentation Comments › Contained Item Comments

Adding example code blocks in your documentation comments can help demonstrate
how to use your library and has an additional bonus: Running `cargo test` will
run the code examples in your documentation as tests! Nothing is better than
documentation with examples. But nothing is worse than examples that don’t work
because the code has changed since the documentation was written. If we run
`cargo test` with the documentation for the `add_one` function from Listing
14-1, we will see a section in the test results that looks like this:
```text
   Doc-tests my_crate

running 1 test
test src/lib.rs - add_one (line 5) ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.27s
```
Now, if we change either the function or the example so that the `assert_eq!`
in the example panics, and run `cargo test` again, we’ll see that the doc tests
catch that the example and the code are out of sync with each other!
The style of doc comment `//!` adds documentation to the item that *contains*
the comments rather than to the items *following* the comments. We typically
use these doc comments inside the crate root file (_src/lib.rs_ by convention)
or inside a module to document the crate or the module as a whole.
For example, to add documentation that describes the purpose of the `my_crate`
crate that contains the `add_one` function, we add documentation comments that
start with `//!` to the beginning of the _src/lib.rs_ file, as shown in Listing
14-2.
Listing 14-2: The documentation for the `my_crate` crate as a whole (src/lib.rs)

Publishing a Crate to Crates.io
Making Useful Documentation Comments
Contained Item Comments


The Rust Programming Language › Publishing a Crate to Crates.io › Making Useful Documentation Comments › Contained Item Comments

```rust,ignore
//! # My Crate
//!
//! `my_crate` is a collection of utilities to make performing certain
//! calculations more convenient.

/// Adds one to the number given.
// --snip--
```
Notice there isn’t any code after the last line that begins with `//!`. Because
we started the comments with `//!` instead of `///`, we’re documenting the item
that contains this comment rather than an item that follows this comment. In
this case, that item is the _src/lib.rs_ file, which is the crate root. These
comments describe the entire crate.
When we run `cargo doc --open`, these comments will display on the front page
of the documentation for `my_crate` above the list of public items in the
crate, as shown in Figure 14-2.
Documentation comments within items are useful for describing crates and
modules especially. Use them to explain the overall purpose of the container to
help your users understand the crate’s organization.

Figure 14-2: The rendered documentation for `my_crate`,
including the comment describing the crate as a whole


The Rust Programming Language › Publishing a Crate to Crates.io › Exporting a Convenient Public API

The structure of your public API is a major consideration when publishing a
crate. People who use your crate are less familiar with the structure than you
are and might have difficulty finding the pieces they want to use if your crate
has a large module hierarchy.
In Chapter 7, we covered how to make items public using the `pub` keyword, and
how to bring items into a scope with the `use` keyword. However, the structure
that makes sense to you while you’re developing a crate might not be very
convenient for your users. You might want to organize your structs in a
hierarchy containing multiple levels, but then people who want to use a type
you’ve defined deep in the hierarchy might have trouble finding out that type
exists. They might also be annoyed at having to enter `use
my_crate::some_module::another_module::UsefulType;` rather than `use
my_crate::UsefulType;`.
The good news is that if the structure _isn’t_ convenient for others to use
from another library, you don’t have to rearrange your internal organization:
Instead, you can re-export items to make a public structure that’s different
from your private structure by using `pub use`. *Re-exporting* takes a public
item in one location and makes it public in another location, as if it were
defined in the other location instead.
For example, say we made a library named `art` for modeling artistic concepts.
Within this library are two modules: a `kinds` module containing two enums
named `PrimaryColor` and `SecondaryColor` and a `utils` module containing a
function named `mix`, as shown in Listing 14-3.
Listing 14-3: An `art` library with items organized into `kinds` and `utils` modules (src/lib.rs)

Publishing a Crate to Crates.io
Exporting a Convenient Public API


The Rust Programming Language › Publishing a Crate to Crates.io › Exporting a Convenient Public API

```rust,noplayground,test_harness
//! # Art
//!
//! A library for modeling artistic concepts.

pub mod kinds {
    /// The primary colors according to the RYB color model.
    pub enum PrimaryColor {
        Red,
        Yellow,
        Blue,
    }

    /// The secondary colors according to the RYB color model.
    pub enum SecondaryColor {
        Orange,
        Green,
        Purple,
    }
}

pub mod utils {
    use crate::kinds::*;

    /// Combines two primary colors in equal amounts to create
    /// a secondary color.
    pub fn mix(c1: PrimaryColor, c2: PrimaryColor) -> SecondaryColor {
        // --snip--
    }
}
```
Figure 14-3 shows what the front page of the documentation for this crate
generated by `cargo doc` would look like.
<img alt="Rendered documentation for the `art` crate that lists the `kinds` and `utils` modules" src="img/trpl14-03.png" class="center" />
Figure 14-3: The front page of the documentation for `art`
that lists the `kinds` and `utils` modules
Note that the `PrimaryColor` and `SecondaryColor` types aren’t listed on the
front page, nor is the `mix` function. We have to click `kinds` and `utils` to
see them.
Another crate that depends on this library would need `use` statements that
bring the items from `art` into scope, specifying the module structure that’s
currently defined. Listing 14-4 shows an example of a crate that uses the
`PrimaryColor` and `mix` items from the `art` crate.
Listing 14-4: A crate using the `art` crate’s items with its internal structure exported (src/main.rs)


The Rust Programming Language › Publishing a Crate to Crates.io › Exporting a Convenient Public API

```rust,ignore
use art::kinds::PrimaryColor;
use art::utils::mix;

fn main() {
    let red = PrimaryColor::Red;
    let yellow = PrimaryColor::Yellow;
    mix(red, yellow);
}
```
The author of the code in Listing 14-4, which uses the `art` crate, had to
figure out that `PrimaryColor` is in the `kinds` module and `mix` is in the
`utils` module. The module structure of the `art` crate is more relevant to
developers working on the `art` crate than to those using it. The internal
structure doesn’t contain any useful information for someone trying to
understand how to use the `art` crate, but rather causes confusion because
developers who use it have to figure out where to look, and must specify the
module names in the `use` statements.
To remove the internal organization from the public API, we can modify the
`art` crate code in Listing 14-3 to add `pub use` statements to re-export the
items at the top level, as shown in Listing 14-5.
Listing 14-5: Adding `pub use` statements to re-export items (src/lib.rs)
```rust,ignore
//! # Art
//!
//! A library for modeling artistic concepts.

pub use self::kinds::PrimaryColor;
pub use self::kinds::SecondaryColor;
pub use self::utils::mix;

pub mod kinds {
    // --snip--
}

pub mod utils {
    // --snip--
}
```
The API documentation that `cargo doc` generates for this crate will now list
and link re-exports on the front page, as shown in Figure 14-4, making the
`PrimaryColor` and `SecondaryColor` types and the `mix` function easier to find.


The Rust Programming Language › Publishing a Crate to Crates.io › Exporting a Convenient Public API

<img alt="Rendered documentation for the `art` crate with the re-exports on the front page" src="img/trpl14-04.png" class="center" />
Figure 14-4: The front page of the documentation for `art`
that lists the re-exports
The `art` crate users can still see and use the internal structure from Listing
14-3 as demonstrated in Listing 14-4, or they can use the more convenient
structure in Listing 14-5, as shown in Listing 14-6.
Listing 14-6: A program using the re-exported items from the `art` crate (src/main.rs)
```rust,ignore
use art::PrimaryColor;
use art::mix;

fn main() {
    // --snip--
}
```
In cases where there are many nested modules, re-exporting the types at the top
level with `pub use` can make a significant difference in the experience of
people who use the crate. Another common use of `pub use` is to re-export
definitions of a dependency in the current crate to make that crate's
definitions part of your crate’s public API.
Creating a useful public API structure is more an art than a science, and you
can iterate to find the API that works best for your users. Choosing `pub use`
gives you flexibility in how you structure your crate internally and decouples
that internal structure from what you present to your users. Look at some of
the code of crates you’ve installed to see if their internal structure differs
from their public API.


The Rust Programming Language › Publishing a Crate to Crates.io › Setting Up a Crates.io Account

Before you can publish any crates, you need to create an account on
crates.io and get an API token. To do so,
visit the home page at crates.io and log
in via a GitHub account. (The GitHub account is currently a requirement, but
the site might support other ways of creating an account in the future.) Once
you’re logged in, visit your account settings at
https://crates.io/me/ and retrieve your
API key. Then, run the `cargo login` command and paste your API key when prompted, like this:
```console
$ cargo login
abcdefghijklmnopqrstuvwxyz012345
```
This command will inform Cargo of your API token and store it locally in
_~/.cargo/credentials.toml_. Note that this token is a secret: Do not share
it with anyone else. If you do share it with anyone for any reason, you should
revoke it and generate a new token on crates.io
.

Publishing a Crate to Crates.io
Setting Up a Crates.io Account


The Rust Programming Language › Publishing a Crate to Crates.io › Adding Metadata to a New Crate

Let’s say you have a crate you want to publish. Before publishing, you’ll need
to add some metadata in the `[package]` section of the crate’s _Cargo.toml_
file.
Your crate will need a unique name. While you’re working on a crate locally,
you can name a crate whatever you’d like. However, crate names on
crates.io are allocated on a first-come,
first-served basis. Once a crate name is taken, no one else can publish a crate
with that name. Before attempting to publish a crate, search for the name you
want to use. If the name has been used, you will need to find another name and
edit the `name` field in the _Cargo.toml_ file under the `[package]` section to
use the new name for publishing, like so:
Filename: Cargo.toml
```toml
[package]
name = "guessing_game"
```
Even if you’ve chosen a unique name, when you run `cargo publish` to publish
the crate at this point, you’ll get a warning and then an error:
```console
$ cargo publish
    Updating crates.io index
warning: manifest has no description, license, license-file, documentation, homepage or repository.
See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
--snip--
error: failed to publish to registry at https://crates.io

Caused by:
  the remote server responded with an error (status 400 Bad Request): missing or empty metadata fields: description, license. Please see https://doc.rust-lang.org/cargo/reference/manifest.html for more information on configuring these fields
```

Publishing a Crate to Crates.io
Adding Metadata to a New Crate


The Rust Programming Language › Publishing a Crate to Crates.io › Adding Metadata to a New Crate

This results in an error because you’re missing some crucial information: A
description and license are required so that people will know what your crate
does and under what terms they can use it. In _Cargo.toml_, add a description
that's just a sentence or two, because it will appear with your crate in search
results. For the `license` field, you need to give a _license identifier
value_. The Linux Foundation’s Software Package Data Exchange (SPDX)
lists the identifiers you can use for this value. For example, to specify that
you’ve licensed your crate using the MIT License, add the `MIT` identifier:
Filename: Cargo.toml
```toml
[package]
name = "guessing_game"
license = "MIT"
```
If you want to use a license that doesn’t appear in the SPDX, you need to place
the text of that license in a file, include the file in your project, and then
use `license-file` to specify the name of that file instead of using the
`license` key.
Guidance on which license is appropriate for your project is beyond the scope
of this book. Many people in the Rust community license their projects in the
same way as Rust by using a dual license of `MIT OR Apache-2.0`. This practice
demonstrates that you can also specify multiple license identifiers separated
by `OR` to have multiple licenses for your project.
With a unique name, the version, your description, and a license added, the
_Cargo.toml_ file for a project that is ready to publish might look like this:
Filename: Cargo.toml


The Rust Programming Language › Publishing a Crate to Crates.io › Adding Metadata to a New Crate

```toml
[package]
name = "guessing_game"
version = "0.1.0"
edition = "2024"
description = "A fun game where you guess what number the computer has chosen."
license = "MIT OR Apache-2.0"

[dependencies]
```
Cargo’s documentation describes other
metadata you can specify to ensure that others can discover and use your crate
more easily.


The Rust Programming Language › Publishing a Crate to Crates.io › Publishing to Crates.io

Now that you’ve created an account, saved your API token, chosen a name for
your crate, and specified the required metadata, you’re ready to publish!
Publishing a crate uploads a specific version to
crates.io for others to use.
Be careful, because a publish is _permanent_. The version can never be
overwritten, and the code cannot be deleted except in certain circumstances.
One major goal of Crates.io is to act as a permanent archive of code so that
builds of all projects that depend on crates from
crates.io will continue to work. Allowing
version deletions would make fulfilling that goal impossible. However, there is
no limit to the number of crate versions you can publish.
Run the `cargo publish` command again. It should succeed now:
```console
$ cargo publish
    Updating crates.io index
   Packaging guessing_game v0.1.0 (file:///projects/guessing_game)
    Packaged 6 files, 1.2KiB (895.0B compressed)
   Verifying guessing_game v0.1.0 (file:///projects/guessing_game)
   Compiling guessing_game v0.1.0
(file:///projects/guessing_game/target/package/guessing_game-0.1.0)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.19s
   Uploading guessing_game v0.1.0 (file:///projects/guessing_game)
    Uploaded guessing_game v0.1.0 to registry `crates-io`
note: waiting for `guessing_game v0.1.0` to be available at registry
`crates-io`.
You may press ctrl-c to skip waiting; the crate should be available shortly.
   Published guessing_game v0.1.0 at registry `crates-io`
```

Publishing a Crate to Crates.io
Publishing to Crates.io


The Rust Programming Language › Publishing a Crate to Crates.io › Publishing to Crates.io

Congratulations! You’ve now shared your code with the Rust community, and
anyone can easily add your crate as a dependency of their project.


The Rust Programming Language › Publishing a Crate to Crates.io › Publishing a New Version of an Existing Crate

When you’ve made changes to your crate and are ready to release a new version,
you change the `version` value specified in your _Cargo.toml_ file and
republish. Use the Semantic Versioning rules to decide what an
appropriate next version number is, based on the kinds of changes you’ve made.
Then, run `cargo publish` to upload the new version.


The Rust Programming Language › Publishing a Crate to Crates.io › Deprecating Versions from Crates.io

Although you can’t remove previous versions of a crate, you can prevent any
future projects from adding them as a new dependency. This is useful when a
crate version is broken for one reason or another. In such situations, Cargo
supports yanking a crate version.
_Yanking_ a version prevents new projects from depending on that version while
allowing all existing projects that depend on it to continue. Essentially, a
yank means that all projects with a _Cargo.lock_ will not break, and any future
_Cargo.lock_ files generated will not use the yanked version.
To yank a version of a crate, in the directory of the crate that you’ve
previously published, run `cargo yank` and specify which version you want to
yank. For example, if we’ve published a crate named `guessing_game` version
1.0.1 and we want to yank it, then we’d run the following in the project
directory for `guessing_game`:
```console
$ cargo yank --vers 1.0.1
    Updating crates.io index
        Yank guessing_game@1.0.1
```
By adding `--undo` to the command, you can also undo a yank and allow projects
to start depending on a version again:
```console
$ cargo yank --vers 1.0.1 --undo
    Updating crates.io index
      Unyank guessing_game@1.0.1
```
A yank _does not_ delete any code. It cannot, for example, delete accidentally
uploaded secrets. If that happens, you must reset those secrets immediately.

Publishing a Crate to Crates.io
Deprecating Versions from Crates.io


The Rust Programming Language › Cargo Workspaces

In Chapter 12, we built a package that included a binary crate and a library
crate. As your project develops, you might find that the library crate
continues to get bigger and you want to split your package further into
multiple library crates. Cargo offers a feature called _workspaces_ that can
help manage multiple related packages that are developed in tandem.


The Rust Programming Language › Cargo Workspaces › Creating a Workspace

A _workspace_ is a set of packages that share the same _Cargo.lock_ and output
directory. Let’s make a project using a workspace—we’ll use trivial code so
that we can concentrate on the structure of the workspace. There are multiple
ways to structure a workspace, so we'll just show one common way. We’ll have a
workspace containing a binary and two libraries. The binary, which will provide
the main functionality, will depend on the two libraries. One library will
provide an `add_one` function and the other library an `add_two` function.
These three crates will be part of the same workspace. We’ll start by creating
a new directory for the workspace:
```console
$ mkdir add
$ cd add
```
Next, in the _add_ directory, we create the _Cargo.toml_ file that will
configure the entire workspace. This file won’t have a `[package]` section.
Instead, it will start with a `[workspace]` section that will allow us to add
members to the workspace. We also make a point to use the latest and greatest
version of Cargo’s resolver algorithm in our workspace by setting the
`resolver` value to `"3"`:
Filename: Cargo.toml
```toml
[workspace]
resolver = "3"
```
Next, we’ll create the `adder` binary crate by running `cargo new` within the
_add_ directory:
```console
$ cargo new adder
     Created binary (application) `adder` package
      Adding `adder` as member of workspace at `file:///projects/add`
```
Running `cargo new` inside a workspace also automatically adds the newly created
package to the `members` key in the `[workspace]` definition in the workspace
_Cargo.toml_, like this:
```toml
[workspace]
resolver = "3"
members = ["adder"]
```


The Rust Programming Language › Cargo Workspaces › Creating a Workspace

At this point, we can build the workspace by running `cargo build`. The files
in your _add_ directory should look like this:
```text
├── Cargo.lock
├── Cargo.toml
├── adder
│   ├── Cargo.toml
│   └── src
│       └── main.rs
└── target
```
The workspace has one _target_ directory at the top level that the compiled
artifacts will be placed into; the `adder` package doesn’t have its own
_target_ directory. Even if we were to run `cargo build` from inside the
_adder_ directory, the compiled artifacts would still end up in _add/target_
rather than _add/adder/target_. Cargo structures the _target_ directory in a
workspace like this because the crates in a workspace are meant to depend on
each other. If each crate had its own _target_ directory, each crate would have
to recompile each of the other crates in the workspace to place the artifacts
in its own _target_ directory. By sharing one _target_ directory, the crates
can avoid unnecessary rebuilding.


The Rust Programming Language › Cargo Workspaces › Creating the Second Package in the Workspace

Next, let’s create another member package in the workspace and call it
`add_one`. Generate a new library crate named `add_one`:
```console
$ cargo new add_one --lib
     Created library `add_one` package
      Adding `add_one` as member of workspace at `file:///projects/add`
```
The top-level _Cargo.toml_ will now include the _add_one_ path in the `members`
list:
Filename: Cargo.toml
```toml
[workspace]
resolver = "3"
members = ["adder", "add_one"]
```
Your _add_ directory should now have these directories and files:
```text
├── Cargo.lock
├── Cargo.toml
├── add_one
│   ├── Cargo.toml
│   └── src
│       └── lib.rs
├── adder
│   ├── Cargo.toml
│   └── src
│       └── main.rs
└── target
```
In the _add_one/src/lib.rs_ file, let’s add an `add_one` function:
Filename: add_one/src/lib.rs
```rust,noplayground
pub fn add_one(x: i32) -> i32 {
    x + 1
}
```
Now we can have the `adder` package with our binary depend on the `add_one`
package that has our library. First, we’ll need to add a path dependency on
`add_one` to _adder/Cargo.toml_.
Filename: adder/Cargo.toml
```toml
[dependencies]
add_one = { path = "../add_one" }
```
Cargo doesn’t assume that crates in a workspace will depend on each other, so
we need to be explicit about the dependency relationships.


The Rust Programming Language › Cargo Workspaces › Creating the Second Package in the Workspace

Next, let’s use the `add_one` function (from the `add_one` crate) in the
`adder` crate. Open the _adder/src/main.rs_ file and change the `main`
function to call the `add_one` function, as in Listing 14-7.
Listing 14-7: Using the `add_one` library crate from the `adder` crate (adder/src/main.rs)
```rust,ignore
fn main() {
    let num = 10;
    println!("Hello, world! {num} plus one is {}!", add_one::add_one(num));
}
```
Let’s build the workspace by running `cargo build` in the top-level _add_
directory!
```console
$ cargo build
   Compiling add_one v0.1.0 (file:///projects/add/add_one)
   Compiling adder v0.1.0 (file:///projects/add/adder)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.22s
```
To run the binary crate from the _add_ directory, we can specify which package
in the workspace we want to run by using the `-p` argument and the package name
with `cargo run`:
```console
$ cargo run -p adder
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/adder`
Hello, world! 10 plus one is 11!
```
This runs the code in _adder/src/main.rs_, which depends on the `add_one` crate.


The Rust Programming Language › Cargo Workspaces › Depending on an External Package

Notice that the workspace has only one _Cargo.lock_ file at the top level,
rather than having a _Cargo.lock_ in each crate’s directory. This ensures that
all crates are using the same version of all dependencies. If we add the `rand`
package to the _adder/Cargo.toml_ and _add_one/Cargo.toml_ files, Cargo will
resolve both of those to one version of `rand` and record that in the one
_Cargo.lock_. Making all crates in the workspace use the same dependencies
means the crates will always be compatible with each other. Let’s add the
`rand` crate to the `[dependencies]` section in the _add_one/Cargo.toml_ file
so that we can use the `rand` crate in the `add_one` crate:
Filename: add_one/Cargo.toml
```toml
[dependencies]
rand = "0.10.1"
```
We can now add `use rand;` to the _add_one/src/lib.rs_ file, and building the
whole workspace by running `cargo build` in the _add_ directory will bring in
and compile the `rand` crate. We will get one warning because we aren’t
referring to the `rand` we brought into scope:

Cargo Workspaces
Depending on an External Package


The Rust Programming Language › Cargo Workspaces › Depending on an External Package

```console
$ cargo build
    Updating crates.io index
  Downloaded rand v0.10.1
   --snip--
   Compiling rand v0.10.1
   Compiling add_one v0.1.0 (file:///projects/add/add_one)
warning: unused import: `rand`
 --> add_one/src/lib.rs:1:5
  |
1 | use rand;
  |     ^^^^
  |
  = note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default

warning: `add_one` (lib) generated 1 warning (run `cargo fix --lib -p add_one` to apply 1 suggestion)
   Compiling adder v0.1.0 (file:///projects/add/adder)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.95s
```
The top-level _Cargo.lock_ now contains information about the dependency of
`add_one` on `rand`. However, even though `rand` is used somewhere in the
workspace, we can’t use it in other crates in the workspace unless we add
`rand` to their _Cargo.toml_ files as well. For example, if we add `use rand;`
to the _adder/src/main.rs_ file for the `adder` package, we’ll get an error:
```console
$ cargo build
  --snip--
   Compiling adder v0.1.0 (file:///projects/add/adder)
error[E0432]: unresolved import `rand`
 --> adder/src/main.rs:2:5
  |
2 | use rand;
  |     ^^^^ no external crate `rand`
```


The Rust Programming Language › Cargo Workspaces › Depending on an External Package

To fix this, edit the _Cargo.toml_ file for the `adder` package and indicate
that `rand` is a dependency for it as well. Building the `adder` package will
add `rand` to the list of dependencies for `adder` in _Cargo.lock_, but no
additional copies of `rand` will be downloaded. Cargo will ensure that every
crate in every package in the workspace using the `rand` package will use the
same version as long as they specify compatible versions of `rand`, saving us
space and ensuring that the crates in the workspace will be compatible with
each other.
If crates in the workspace specify incompatible versions of the same
dependency, Cargo will resolve each of them but will still try to resolve as
few versions as possible.


The Rust Programming Language › Cargo Workspaces › Adding a Test to a Workspace

For another enhancement, let’s add a test of the `add_one::add_one` function
within the `add_one` crate:
Filename: add_one/src/lib.rs
```rust,noplayground
pub fn add_one(x: i32) -> i32 {
    x + 1
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_works() {
        assert_eq!(3, add_one(2));
    }
}
```
Now run `cargo test` in the top-level _add_ directory. Running `cargo test` in
a workspace structured like this one will run the tests for all the crates in
the workspace:

Cargo Workspaces
Adding a Test to a Workspace


The Rust Programming Language › Cargo Workspaces › Adding a Test to a Workspace

```console
$ cargo test
   Compiling add_one v0.1.0 (file:///projects/add/add_one)
   Compiling adder v0.1.0 (file:///projects/add/adder)
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.20s
     Running unittests src/lib.rs (target/debug/deps/add_one-93c49ee75dc46543)

running 1 test
test tests::it_works ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running unittests src/main.rs (target/debug/deps/adder-3a47283c568d2b6a)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

   Doc-tests add_one

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
```
The first section of the output shows that the `it_works` test in the `add_one`
crate passed. The next section shows that zero tests were found in the `adder`
crate, and then the last section shows that zero documentation tests were found
in the `add_one` crate.
We can also run tests for one particular crate in a workspace from the
top-level directory by using the `-p` flag and specifying the name of the crate
we want to test:


The Rust Programming Language › Cargo Workspaces › Adding a Test to a Workspace

```console
$ cargo test -p add_one
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.00s
     Running unittests src/lib.rs (target/debug/deps/add_one-93c49ee75dc46543)

running 1 test
test tests::it_works ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

   Doc-tests add_one

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
```
This output shows `cargo test` only ran the tests for the `add_one` crate and
didn’t run the `adder` crate tests.
If you publish the crates in the workspace to
crates.io, each crate in the workspace
will need to be published separately. Like `cargo test`, we can publish a
particular crate in our workspace by using the `-p` flag and specifying the
name of the crate we want to publish.
For additional practice, add an `add_two` crate to this workspace in a similar
way as the `add_one` crate!
As your project grows, consider using a workspace: It enables you to work with
smaller, easier-to-understand components than one big blob of code.
Furthermore, keeping the crates in a workspace can make coordination between
crates easier if they are often changed at the same time.


The Rust Programming Language › Installing Binaries with `cargo install`

The `cargo install` command allows you to install and use binary crates
locally. This isn’t intended to replace system packages; it’s meant to be a
convenient way for Rust developers to install tools that others have shared on
crates.io. Note that you can only install
packages that have binary targets. A _binary target_ is the runnable program
that is created if the crate has a _src/main.rs_ file or another file specified
as a binary, as opposed to a library target that isn’t runnable on its own but
is suitable for including within other programs. Usually, crates have
information in the README file about whether a crate is a library, has a
binary target, or both.
All binaries installed with `cargo install` are stored in the installation
root’s _bin_ folder. If you installed Rust using _rustup.rs_ and don’t have any
custom configurations, this directory will be *$HOME/.cargo/bin*. Ensure that
this directory is in your `$PATH` to be able to run programs you’ve installed
with `cargo install`.
For example, in Chapter 12 we mentioned that there’s a Rust implementation of
the `grep` tool called `ripgrep` for searching files. To install `ripgrep`, we
can run the following:
```console
$ cargo install ripgrep
    Updating crates.io index
  Downloaded ripgrep v14.1.1
  Downloaded 1 crate (213.6 KB) in 0.40s
  Installing ripgrep v14.1.1
--snip--
   Compiling grep v0.3.2
    Finished `release` profile [optimized + debuginfo] target(s) in 6.73s
  Installing ~/.cargo/bin/rg
   Installed package `ripgrep v14.1.1` (executable `rg`)
```


The Rust Programming Language › Installing Binaries with `cargo install`

The second-to-last line of the output shows the location and the name of the
installed binary, which in the case of `ripgrep` is `rg`. As long as the
installation directory is in your `$PATH`, as mentioned previously, you can
then run `rg --help` and start using a faster, Rustier tool for searching files!


The Rust Programming Language › Extending Cargo with Custom Commands

Cargo is designed so that you can extend it with new subcommands without having
to modify it. If a binary in your `$PATH` is named `cargo-something`, you can
run it as if it were a Cargo subcommand by running `cargo something`. Custom
commands like this are also listed when you run `cargo --list`. Being able to
use `cargo install` to install extensions and then run them just like the
built-in Cargo tools is a super-convenient benefit of Cargo’s design!


The Rust Programming Language › Summary

Sharing code with Cargo and crates.io is
part of what makes the Rust ecosystem useful for many different tasks. Rust’s
standard library is small and stable, but crates are easy to share, use, and
improve on a timeline different from that of the language. Don’t be shy about
sharing code that’s useful to you on crates.io
; it’s likely that it will be useful to someone else as well!


The Rust Programming Language › Smart Pointers

A pointer is a general concept for a variable that contains an address in
memory. This address refers to, or “points at,” some other data. The most
common kind of pointer in Rust is a reference, which you learned about in
Chapter 4. References are indicated by the `&` symbol and borrow the value they
point to. They don’t have any special capabilities other than referring to
data, and they have no overhead.
_Smart pointers_, on the other hand, are data structures that act like a
pointer but also have additional metadata and capabilities. The concept of
smart pointers isn’t unique to Rust: Smart pointers originated in C++ and exist
in other languages as well. Rust has a variety of smart pointers defined in the
standard library that provide functionality beyond that provided by references.
To explore the general concept, we’ll look at a couple of different examples of
smart pointers, including a _reference counting_ smart pointer type. This
pointer enables you to allow data to have multiple owners by keeping track of
the number of owners and, when no owners remain, cleaning up the data.
In Rust, with its concept of ownership and borrowing, there is an additional
difference between references and smart pointers: While references only borrow
data, in many cases smart pointers _own_ the data they point to.
Smart pointers are usually implemented using structs. Unlike an ordinary
struct, smart pointers implement the `Deref` and `Drop` traits. The `Deref`
trait allows an instance of the smart pointer struct to behave like a reference
so that you can write your code to work with either references or smart
pointers. The `Drop` trait allows you to customize the code that’s run when an
instance of the smart pointer goes out of scope. In this chapter, we’ll discuss
both of these traits and demonstrate why they’re important to smart pointers.


The Rust Programming Language › Smart Pointers

Given that the smart pointer pattern is a general design pattern used
frequently in Rust, this chapter won’t cover every existing smart pointer. Many
libraries have their own smart pointers, and you can even write your own. We’ll
cover the most common smart pointers in the standard library:
- `Box<T>`, for allocating values on the heap
- `Rc<T>`, a reference counting type that enables multiple ownership
- `Ref<T>` and `RefMut<T>`, accessed through `RefCell<T>`, a type that enforces
  the borrowing rules at runtime instead of compile time
In addition, we’ll cover the _interior mutability_ pattern where an immutable
type exposes an API for mutating an interior value. We’ll also discuss
reference cycles: how they can leak memory and how to prevent them.
Let’s dive in!


The Rust Programming Language › Using `Box<T>` to Point to Data on the Heap

The most straightforward smart pointer is a box, whose type is written
`Box<T>`. _Boxes_ allow you to store data on the heap rather than the stack.
What remains on the stack is the pointer to the heap data. Refer to Chapter 4
to review the difference between the stack and the heap.
Boxes don’t have performance overhead, other than storing their data on the
heap instead of on the stack. But they don’t have many extra capabilities
either. You’ll use them most often in these situations:
- When you have a type whose size can’t be known at compile time, and you want
  to use a value of that type in a context that requires an exact size
- When you have a large amount of data, and you want to transfer ownership but
  ensure that the data won’t be copied when you do so
- When you want to own a value, and you care only that it’s a type that
  implements a particular trait rather than being of a specific type
We’ll demonstrate the first situation in “Enabling Recursive Types with
Boxes”. In the second
case, transferring ownership of a large amount of data can take a long time
because the data is copied around on the stack. To improve performance in this
situation, we can store the large amount of data on the heap in a box. Then,
only the small amount of pointer data is copied around on the stack, while the
data it references stays in one place on the heap. The third case is known as a
_trait object_, and “Using Trait Objects to Abstract over Shared
Behavior” in Chapter 18 is devoted to that
topic. So, what you learn here you’ll apply again in that section!


The Rust Programming Language › Using `Box<T>` to Point to Data on the Heap › Storing Data on the Heap

Before we discuss the heap storage use case for `Box<T>`, we’ll cover the
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.
Listing 15-1: Storing an `i32` value on the heap using a box (src/main.rs)
```rust
fn main() {
    let b = Box::new(5);
    println!("b = {b}");
}
```
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
this case, we can access the data in the box similarly to how we would if this
data were on the stack. Just like any owned value, when a box goes out of
scope, as `b` does at the end of `main`, it will be deallocated. The
deallocation happens both for the box (stored on the stack) and the data it
points to (stored on the heap).
Putting a single value on the heap isn’t very useful, so you won’t use boxes by
themselves in this way very often. Having values like a single `i32` on the
stack, where they’re stored by default, is more appropriate in the majority of
situations. Let’s look at a case where boxes allow us to define types that we
wouldn’t be allowed to define if we didn’t have boxes.


The Rust Programming Language › Using `Box<T>` to Point to Data on the Heap › Enabling Recursive Types with Boxes › Understanding the Cons List

A value of a _recursive type_ can have another value of the same type as part of
itself. Recursive types pose an issue because Rust needs to know at compile time
how much space a type takes up. However, the nesting of values of recursive
types could theoretically continue infinitely, so Rust can’t know how much space
the value needs. Because boxes have a known size, we can enable recursive types
by inserting a box in the recursive type definition.
As an example of a recursive type, let’s explore the cons list. This is a data
type commonly found in functional programming languages. The cons list type
we’ll define is straightforward except for the recursion; therefore, the
concepts in the example we’ll work with will be useful anytime you get into
more complex situations involving recursive types.
A _cons list_ is a data structure that comes from the Lisp programming language
and its dialects, is made up of nested pairs, and is the Lisp version of a
linked list. Its name comes from the `cons` function (short for _construct
function_) in Lisp that constructs a new pair from its two arguments. By
calling `cons` on a pair consisting of a value and another pair, we can
construct cons lists made up of recursive pairs.
For example, here’s a pseudocode representation of a cons list containing the
list `1, 2, 3` with each pair in parentheses:
```text
(1, (2, (3, Nil)))
```
Each item in a cons list contains two elements: the value of the current item
and of the next item. The last item in the list contains only a value called
`Nil` without a next item. A cons list is produced by recursively calling the
`cons` function. The canonical name to denote the base case of the recursion is
`Nil`. Note that this is not the same as the “null” or “nil” concept discussed
in Chapter 6, which is an invalid or absent value.


The Rust Programming Language › Using `Box<T>` to Point to Data on the Heap › Enabling Recursive Types with Boxes › Understanding the Cons List

The cons list isn’t a commonly used data structure in Rust. Most of the time
when you have a list of items in Rust, `Vec<T>` is a better choice to use.
Other, more complex recursive data types _are_ useful in various situations,
but by starting with the cons list in this chapter, we can explore how boxes
let us define a recursive data type without much distraction.
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.
Listing 15-2: The first attempt at defining an enum to represent a cons list data structure of `i32` values (src/main.rs)
```rust,ignore,does_not_compile
enum List {
    Cons(i32, List),
    Nil,
}
```
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
discussed in Chapter 10, to define a cons list type that could store values of
any type.
Using the `List` type to store the list `1, 2, 3` would look like the code in
Listing 15-3.
Listing 15-3: Using the `List` enum to store the list `1, 2, 3` (src/main.rs)
```rust,ignore,does_not_compile
// --snip--

use crate::List::{Cons, Nil};

fn main() {
    let list = Cons(1, Cons(2, Cons(3, Nil)));
}
```


The Rust Programming Language › Using `Box<T>` to Point to Data on the Heap › Enabling Recursive Types with Boxes › Computing the Size of a Non-Recursive Type

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
is one more `Cons` value that holds `3` and a `List` value, which is finally
`Nil`, the non-recursive variant that signals the end of the list.
If we try to compile the code in Listing 15-3, we get the error shown in
Listing 15-4.
Listing 15-4: The error we get when attempting to define a recursive enum
```console
$ cargo run
   Compiling cons-list v0.1.0 (file:///projects/cons-list)
error[E0072]: recursive type `List` has infinite size
 --> src/main.rs:1:1
  |
1 | enum List {
  | ^^^^^^^^^
2 |     Cons(i32, List),
  |               ---- recursive without indirection
  |
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
  |
2 |     Cons(i32, Box<List>),
  |               ++++    +

For more information about this error, try `rustc --explain E0072`.
error: could not compile `cons-list` (bin "cons-list") due to 1 previous error
```
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
directly. As a result, Rust can’t figure out how much space it needs to store a
`List` value. Let’s break down why we get this error. First, we’ll look at how
Rust decides how much space it needs to store a value of a non-recursive type.


The Rust Programming Language › Using `Box<T>` to Point to Data on the Heap › Enabling Recursive Types with Boxes › Computing the Size of a Non-Recursive Type

Recall the `Message` enum we defined in Listing 6-2 when we discussed enum
definitions in Chapter 6:
```rust
enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}
```
To determine how much space to allocate for a `Message` value, Rust goes
through each of the variants to see which variant needs the most space. Rust
sees that `Message::Quit` doesn’t need any space, `Message::Move` needs enough
space to store two `i32` values, and so forth. Because only one variant will be
used, the most space a `Message` value will need is the space it would take to
store the largest of its variants.
Contrast this with what happens when Rust tries to determine how much space a
recursive type like the `List` enum in Listing 15-2 needs. The compiler starts
by looking at the `Cons` variant, which holds a value of type `i32` and a value
of type `List`. Therefore, `Cons` needs an amount of space equal to the size of
an `i32` plus the size of a `List`. To figure out how much memory the `List`
type needs, the compiler looks at the variants, starting with the `Cons`
variant. The `Cons` variant holds a value of type `i32` and a value of type
`List`, and this process continues infinitely, as shown in Figure 15-1.


The Rust Programming Language › Using `Box<T>` to Point to Data on the Heap › Enabling Recursive Types with Boxes › Getting a Recursive Type with a Known Size

<img alt="An infinite Cons list: a rectangle labeled 'Cons' split into two smaller rectangles. The first smaller rectangle holds the label 'i32', and the second smaller rectangle holds the label 'Cons' and a smaller version of the outer 'Cons' rectangle. The 'Cons' rectangles continue to hold smaller and smaller versions of themselves until the smallest comfortably sized rectangle holds an infinity symbol, indicating that this repetition goes on forever." src="img/trpl15-01.svg" class="center" style="width: 50%;" />
Figure 15-1: An infinite `List` consisting of infinite
`Cons` variants
Because Rust can’t figure out how much space to allocate for recursively
defined types, the compiler gives an error with this helpful suggestion:
```text
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
  |
2 |     Cons(i32, Box<List>),
  |               ++++    +
```
In this suggestion, _indirection_ means that instead of storing a value
directly, we should change the data structure to store the value indirectly by
storing a pointer to the value instead.
Because a `Box<T>` is a pointer, Rust always knows how much space a `Box<T>`
needs: A pointer’s size doesn’t change based on the amount of data it’s
pointing to. This means we can put a `Box<T>` inside the `Cons` variant instead
of another `List` value directly. The `Box<T>` will point to the next `List`
value that will be on the heap rather than inside the `Cons` variant.
Conceptually, we still have a list, created with lists holding other lists, but
this implementation is now more like placing the items next to one another
rather than inside one another.


The Rust Programming Language › Using `Box<T>` to Point to Data on the Heap › Enabling Recursive Types with Boxes › Getting a Recursive Type with a Known Size

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.
Listing 15-5 (src/main.rs)
```rust
enum List {
    Cons(i32, Box<List>),
    Nil,
}

use crate::List::{Cons, Nil};

fn main() {
    let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
}
```
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 on the
stack than the `Cons` variant. We now know that any `List` value will take up
the size of an `i32` plus the size of a box’s pointer data. By using a box,
we’ve broken the infinite, recursive chain, so the compiler can figure out the
size it needs to store a `List` value. Figure 15-2 shows what the `Cons`
variant looks like now.

Figure 15-2: A `List` that is not infinitely sized,
because `Cons` holds a `Box`


The Rust Programming Language › Using `Box<T>` to Point to Data on the Heap › Enabling Recursive Types with Boxes › Getting a Recursive Type with a Known Size

Boxes provide only the indirection and heap allocation; they don’t have any
other special capabilities, like those we’ll see with the other smart pointer
types. They also don’t have the performance overhead that these special
capabilities incur, so they can be useful in cases like the cons list where the
indirection is the only feature we need. We’ll look at more use cases for boxes
in Chapter 18.
The `Box<T>` type is a smart pointer because it implements the `Deref` trait,
which allows `Box<T>` values to be treated like references. When a `Box<T>`
value goes out of scope, the heap data that the box is pointing to is cleaned
up as well because of the `Drop` trait implementation. These two traits will be
even more important to the functionality provided by the other smart pointer
types we’ll discuss in the rest of this chapter. Let’s explore these two traits
in more detail.


The Rust Programming Language › Treating Smart Pointers Like Regular References

Implementing the `Deref` trait allows you to customize the behavior of the
_dereference operator_ `*` (not to be confused with the multiplication or glob
operator). By implementing `Deref` in such a way that a smart pointer can be
treated like a regular reference, you can write code that operates on
references and use that code with smart pointers too.
Let’s first look at how the dereference operator works with regular references.
Then, we’ll try to define a custom type that behaves like `Box<T>` and see why
the dereference operator doesn’t work like a reference on our newly defined
type. We’ll explore how implementing the `Deref` trait makes it possible for
smart pointers to work in ways similar to references. Then, we’ll look at
Rust’s deref coercion feature and how it lets us work with either references or
smart pointers.


The Rust Programming Language › Treating Smart Pointers Like Regular References › Following the Reference to the Value

A regular reference is a type of pointer, and one way to think of a pointer is
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.
Listing 15-6: Using the dereference operator to follow a reference to an `i32` value (src/main.rs)
```rust
fn main() {
    let x = 5;
    let y = &x;

    assert_eq!(5, x);
    assert_eq!(5, *y);
}
```
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
assertion about the value in `y`, we have to use `*y` to follow the reference
to the value it’s pointing to (hence, _dereference_) so that the compiler can
compare the actual value. Once we dereference `y`, we have access to the
integer value `y` is pointing to that we can compare with `5`.
If we tried to write `assert_eq!(5, y);` instead, we would get this compilation
error:


The Rust Programming Language › Treating Smart Pointers Like Regular References › Following the Reference to the Value

```console
$ cargo run
   Compiling deref-example v0.1.0 (file:///projects/deref-example)
error[E0277]: can't compare `{integer}` with `&{integer}`
 --> src/main.rs:6:5
  |
6 |     assert_eq!(5, y);
  |     ^^^^^^^^^^^^^^^^ no implementation for `{integer} == &{integer}`
  |
  = help: the trait `PartialEq<&{integer}>` is not implemented for `{integer}`
  = help: the following other types implement trait `PartialEq<Rhs>`:
            f128
            f16
            f32
            f64
            i128
            i16
            i32
            i64
          and 8 others

For more information about this error, try `rustc --explain E0277`.
error: could not compile `deref-example` (bin "deref-example") due to 1 previous error
```
Comparing a number and a reference to a number isn’t allowed because they’re
different types. We must use the dereference operator to follow the reference
to the value it’s pointing to.


The Rust Programming Language › Treating Smart Pointers Like Regular References › Using `Box<T>` Like a Reference

We can rewrite the code in Listing 15-6 to use a `Box<T>` instead of a
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.
Listing 15-7 (src/main.rs)
```rust
fn main() {
    let x = 5;
    let y = Box::new(x);

    assert_eq!(5, x);
    assert_eq!(5, *y);
}
```
The main difference between Listing 15-7 and Listing 15-6 is that here we set
`y` to be an instance of a box pointing to a copied value of `x` rather than a
reference pointing to the value of `x`. In the last assertion, we can use the
dereference operator to follow the box’s pointer in the same way that we did
when `y` was a reference. Next, we’ll explore what is special about `Box<T>`
that enables us to use the dereference operator by defining our own box type.


The Rust Programming Language › Treating Smart Pointers Like Regular References › Defining Our Own Smart Pointer

Let’s build a wrapper type similar to the `Box<T>` type provided by the
standard library to experience how smart pointer types behave differently from
references by default. Then, we’ll look at how to add the ability to use the
dereference operator.
Note: There’s one big difference between the `MyBox<T>` type we’re about to
build and the real `Box<T>`: Our version will not store its data on the heap.
We are focusing this example on `Deref`, so where the data is actually stored
is less important than the pointer-like behavior.
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>`.
Listing 15-8 (src/main.rs)
```rust
struct MyBox<T>(T);

impl<T> MyBox<T> {
    fn new(x: T) -> MyBox<T> {
        MyBox(x)
    }
}
```
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
with one element of type `T`. The `MyBox::new` function takes one parameter of
type `T` and returns a `MyBox` instance that holds the value passed in.
Let’s try adding the `main` function in Listing 15-7 to Listing 15-8 and
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`.
Listing 15-9 (src/main.rs)


The Rust Programming Language › Treating Smart Pointers Like Regular References › Defining Our Own Smart Pointer

```rust,ignore,does_not_compile
fn main() {
    let x = 5;
    let y = MyBox::new(x);

    assert_eq!(5, x);
    assert_eq!(5, *y);
}
```
Here’s the resultant compilation error:
```console
$ cargo run
   Compiling deref-example v0.1.0 (file:///projects/deref-example)
error[E0614]: type `MyBox<{integer}>` cannot be dereferenced
  --> src/main.rs:14:19
   |
14 |     assert_eq!(5, *y);
   |                   ^^ can't be dereferenced

For more information about this error, try `rustc --explain E0614`.
error: could not compile `deref-example` (bin "deref-example") due to 1 previous error
```
Our `MyBox<T>` type can’t be dereferenced because we haven’t implemented that
ability on our type. To enable dereferencing with the `*` operator, we
implement the `Deref` trait.


The Rust Programming Language › Treating Smart Pointers Like Regular References › Implementing the `Deref` Trait

As discussed in “Implementing a Trait on a Type” in
Chapter 10, to implement a trait we need to provide implementations for the
trait’s required methods. The `Deref` trait, provided 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<T>`.
Listing 15-10 (src/main.rs)
```rust
use std::ops::Deref;

impl<T> Deref for MyBox<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
```
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 generic
parameter, but you don’t need to worry about them for now; we’ll cover them in
more detail in Chapter 20.
We fill in the body of the `deref` method with `&self.0` so that `deref`
returns a reference to the value we want to access with the `*` operator;
recall from “Creating Different Types with Tuple Structs”
 in Chapter 5 that `.0` accesses the first value in a tuple struct.
The `main` function in Listing 15-9 that calls `*` on the `MyBox<T>` value now
compiles, and the assertions pass!


The Rust Programming Language › Treating Smart Pointers Like Regular References › Implementing the `Deref` Trait

Without the `Deref` trait, the compiler can only dereference `&` references.
The `deref` method gives the compiler the ability to take a value of any type
that implements `Deref` and call the `deref` method to get a reference that
it knows how to dereference.
When we entered `*y` in Listing 15-9, behind the scenes Rust actually ran this
code:
```rust,ignore
*(y.deref())
```
Rust substitutes the `*` operator with a call to the `deref` method and then a
plain dereference so that we don’t have to think about whether or not we need
to call the `deref` method. This Rust feature lets us write code that functions
identically whether we have a regular reference or a type that implements
`Deref`.
The reason the `deref` method returns a reference to a value, and that the
plain dereference outside the parentheses in `*(y.deref())` is still necessary,
has to do with the ownership system. If the `deref` method returned the value
directly instead of a reference to the value, the value would be moved out of
`self`. We don’t want to take ownership of the inner value inside `MyBox<T>` in
this case or in most cases where we use the dereference operator.
Note that the `*` operator is replaced with a call to the `deref` method and
then a call to the `*` operator just once, each time we use a `*` in our code.
Because the substitution of the `*` operator does not recurse infinitely, we
end up with data of type `i32`, which matches the `5` in `assert_eq!` in
Listing 15-9.


The Rust Programming Language › Treating Smart Pointers Like Regular References › Using Deref Coercion in Functions and Methods

_Deref coercion_ converts a reference to a type that implements the `Deref`
trait into a reference to another type. For example, deref coercion can convert
`&String` to `&str` because `String` implements the `Deref` trait such that it
returns `&str`. Deref coercion is a convenience Rust performs on arguments to
functions and methods, and it works only on types that implement the `Deref`
trait. It happens automatically when we pass a reference to a particular type’s
value as an argument to a function or method that doesn’t match the parameter
type in the function or method definition. A sequence of calls to the `deref`
method converts the type we provided into the type the parameter needs.
Deref coercion was added to Rust so that programmers writing function and
method calls don’t need to add as many explicit references and dereferences
with `&` and `*`. The deref coercion feature also lets us write more code that
can work for either references or smart pointers.
To see deref coercion in action, let’s use the `MyBox<T>` type we defined in
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.
Listing 15-11: A `hello` function that has the parameter `name` of type `&str` (src/main.rs)
```rust
fn hello(name: &str) {
    println!("Hello, {name}!");
}
```
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.


The Rust Programming Language › Treating Smart Pointers Like Regular References › Using Deref Coercion in Functions and Methods

Listing 15-12 (src/main.rs)
```rust
fn main() {
    let m = MyBox::new(String::from("Rust"));
    hello(&m);
}
```
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
on `MyBox<T>` in Listing 15-10, Rust can turn `&MyBox<String>` into `&String`
by calling `deref`. The standard library provides an implementation of `Deref`
on `String` that returns a string slice, and this is in the API documentation
for `Deref`. Rust calls `deref` again to turn the `&String` into `&str`, which
matches the `hello` function’s definition.
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>`.
Listing 15-13: The code we would have to write if Rust didn’t have deref coercion (src/main.rs)
```rust
fn main() {
    let m = MyBox::new(String::from("Rust"));
    hello(&(*m)[..]);
}
```
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
match the signature of `hello`. This code without deref coercions is harder to
read, write, and understand with all of these symbols involved. Deref coercion
allows Rust to handle these conversions for us automatically.


The Rust Programming Language › Treating Smart Pointers Like Regular References › Using Deref Coercion in Functions and Methods

When the `Deref` trait is defined for the types involved, Rust will analyze the
types and use `Deref::deref` as many times as necessary to get a reference to
match the parameter’s type. The number of times that `Deref::deref` needs to be
inserted is resolved at compile time, so there is no runtime penalty for taking
advantage of deref coercion!


The Rust Programming Language › Treating Smart Pointers Like Regular References › Handling Deref Coercion with Mutable References

Similar to how you use the `Deref` trait to override the `*` operator on
immutable references, you can use the `DerefMut` trait to override the `*`
operator on mutable references.
Rust does deref coercion when it finds types and trait implementations in three
cases:
1. From `&T` to `&U` when `T: Deref<Target=U>`
2. From `&mut T` to `&mut U` when `T: DerefMut<Target=U>`
3. From `&mut T` to `&U` when `T: Deref<Target=U>`
The first two cases are the same except that the second implements mutability.
The first case states that if you have a `&T`, and `T` implements `Deref` to
some type `U`, you can get a `&U` transparently. The second case states that
the same deref coercion happens for mutable references.
The third case is trickier: Rust will also coerce a mutable reference to an
immutable one. But the reverse is _not_ possible: Immutable references will
never coerce to mutable references. Because of the borrowing rules, if you have
a mutable reference, that mutable reference must be the only reference to that
data (otherwise, the program wouldn’t compile). Converting one mutable
reference to one immutable reference will never break the borrowing rules.
Converting an immutable reference to a mutable reference would require that the
initial immutable reference is the only immutable reference to that data, but
the borrowing rules don’t guarantee that. Therefore, Rust can’t make the
assumption that converting an immutable reference to a mutable reference is
possible.


The Rust Programming Language › Running Code on Cleanup with the `Drop` Trait

The second trait important to the smart pointer pattern is `Drop`, which lets
you customize what happens when a value is about to go out of scope. You can
provide an implementation for the `Drop` trait on any type, and that code can
be used to release resources like files or network connections.
We’re introducing `Drop` in the context of smart pointers because the
functionality of the `Drop` trait is almost always used when implementing a
smart pointer. For example, when a `Box<T>` is dropped, it will deallocate the
space on the heap that the box points to.
In some languages, for some types, the programmer must call code to free memory
or resources every time they finish using an instance of those types. Examples
include file handles, sockets, and locks. If the programmer forgets, the system
might become overloaded and crash. In Rust, you can specify that a particular
bit of code be run whenever a value goes out of scope, and the compiler will
insert this code automatically. As a result, you don’t need to be careful about
placing cleanup code everywhere in a program that an instance of a particular
type is finished with—you still won’t leak resources!
You specify the code to run when a value goes out of scope by implementing the
`Drop` trait. The `Drop` trait requires you to implement one method named
`drop` that takes a mutable reference to `self`. To see when Rust calls `drop`,
let’s implement `drop` with `println!` statements for now.
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` method.
Listing 15-14: A `CustomSmartPointer` struct that implements the `Drop` trait where we would put our cleanup code (src/main.rs)


The Rust Programming Language › Running Code on Cleanup with the `Drop` Trait

```rust
struct CustomSmartPointer {
    data: String,
}

impl Drop for CustomSmartPointer {
    fn drop(&mut self) {
        println!("Dropping CustomSmartPointer with data `{}`!", self.data);
    }
}

fn main() {
    let c = CustomSmartPointer {
        data: String::from("my stuff"),
    };
    let d = CustomSmartPointer {
        data: String::from("other stuff"),
    };
    println!("CustomSmartPointers created");
}
```
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
implementation for the `drop` method that calls `println!`. The body of the
`drop` method is where you would place any logic that you wanted to run when an
instance of your type goes out of scope. We’re printing some text here to
demonstrate visually when Rust will call `drop`.
In `main`, we create two instances of `CustomSmartPointer` and then print
`CustomSmartPointers created`. At the end of `main`, our instances of
`CustomSmartPointer` will go out of scope, and Rust will call the code we put
in the `drop` method, printing our final message. Note that we didn’t need to
call the `drop` method explicitly.
When we run this program, we’ll see the following output:
```console
$ cargo run
   Compiling drop-example v0.1.0 (file:///projects/drop-example)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.60s
     Running `target/debug/drop-example`
CustomSmartPointers created
Dropping CustomSmartPointer with data `other stuff`!
Dropping CustomSmartPointer with data `my stuff`!
```


The Rust Programming Language › Running Code on Cleanup with the `Drop` Trait

Rust automatically called `drop` for us when our instances went out of scope,
calling the code we specified. Variables are dropped in the reverse order of
their creation, so `d` was dropped before `c`. This example’s purpose is to
give you a visual guide to how the `drop` method works; usually you would
specify the cleanup code that your type needs to run rather than a print
message.
Unfortunately, it’s not straightforward to disable the automatic `drop`
functionality. Disabling `drop` isn’t usually necessary; the whole point of the
`Drop` trait is that it’s taken care of automatically. Occasionally, however,
you might want to clean up a value early. One example is when using smart
pointers that manage locks: You might want to force the `drop` method that
releases the lock so that other code in the same scope can acquire the lock.
Rust doesn’t let you call the `Drop` trait’s `drop` method manually; instead,
you have to call the `std::mem::drop` function provided by the standard library
if you want to force a value to be dropped before the end of its scope.
Trying to call the `Drop` trait’s `drop` method manually by modifying the
`main` function from Listing 15-14 won’t work, as shown in Listing 15-15.
Listing 15-15: Attempting to call the `drop` method from the `Drop` trait manually to clean up early (src/main.rs)
```rust,ignore,does_not_compile
fn main() {
    let c = CustomSmartPointer {
        data: String::from("some data"),
    };
    println!("CustomSmartPointer created");
    c.drop();
    println!("CustomSmartPointer dropped before the end of main");
}
```
When we try to compile this code, we’ll get this error:


The Rust Programming Language › Running Code on Cleanup with the `Drop` Trait

```console
$ cargo run
   Compiling drop-example v0.1.0 (file:///projects/drop-example)
error[E0040]: explicit use of destructor method
  --> src/main.rs:16:7
   |
16 |     c.drop();
   |       ^^^^ explicit destructor calls not allowed
   |
help: consider using `drop` function
   |
16 -     c.drop();
16 +     drop(c);
   |

For more information about this error, try `rustc --explain E0040`.
error: could not compile `drop-example` (bin "drop-example") due to 1 previous error
```
This error message states that we’re not allowed to explicitly call `drop`. The
error message uses the term _destructor_, which is the general programming term
for a function that cleans up an instance. A _destructor_ is analogous to a
_constructor_, which creates an instance. The `drop` function in Rust is one
particular destructor.
Rust doesn’t let us call `drop` explicitly, because Rust would still
automatically call `drop` on the value at the end of `main`. This would cause a
double free error because Rust would be trying to clean up the same value twice.
We can’t disable the automatic insertion of `drop` when a value goes out of
scope, and we can’t call the `drop` method explicitly. So, if we need to force
a value to be cleaned up early, we use the `std::mem::drop` function.
The `std::mem::drop` function is different from the `drop` method in the `Drop`
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.


The Rust Programming Language › Running Code on Cleanup with the `Drop` Trait

Listing 15-16: Calling `std::mem::drop` to explicitly drop a value before it goes out of scope (src/main.rs)
```rust
fn main() {
    let c = CustomSmartPointer {
        data: String::from("some data"),
    };
    println!("CustomSmartPointer created");
    drop(c);
    println!("CustomSmartPointer dropped before the end of main");
}
```
Running this code will print the following:
```console
$ cargo run
   Compiling drop-example v0.1.0 (file:///projects/drop-example)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.73s
     Running `target/debug/drop-example`
CustomSmartPointer created
Dropping CustomSmartPointer with data `some data`!
CustomSmartPointer dropped before the end of main
```
The text ``Dropping CustomSmartPointer with data `some data`!`` is printed
between the `CustomSmartPointer created` and `CustomSmartPointer dropped before
the end of main` text, showing that the `drop` method code is called to drop
`c` at that point.
You can use code specified in a `Drop` trait implementation in many ways to
make cleanup convenient and safe: For instance, you could use it to create your
own memory allocator! With the `Drop` trait and Rust’s ownership system, you
don’t have to remember to clean up, because Rust does it automatically.
You also don’t have to worry about problems resulting from accidentally
cleaning up values still in use: The ownership system that makes sure
references are always valid also ensures that `drop` gets called only once when
the value is no longer being used.
Now that we’ve examined `Box<T>` and some of the characteristics of smart
pointers, let’s look at a few other smart pointers defined in the standard
library.


The Rust Programming Language › `Rc<T>`, the Reference-Counted Smart Pointer

In the majority of cases, ownership is clear: You know exactly which variable
owns a given value. However, there are cases when a single value might have
multiple owners. For example, in graph data structures, multiple edges might
point to the same node, and that node is conceptually owned by all of the edges
that point to it. A node shouldn’t be cleaned up unless it doesn’t have any
edges pointing to it and so has no owners.
You have to enable multiple ownership explicitly by using the Rust type
`Rc<T>`, which is an abbreviation for _reference counting_. The `Rc<T>` type
keeps track of the number of references to a value to determine whether or not
the value is still in use. If there are zero references to a value, the value
can be cleaned up without any references becoming invalid.
Imagine `Rc<T>` as a TV in a family room. When one person enters to watch TV,
they turn it on. Others can come into the room and watch the TV. When the last
person leaves the room, they turn off the TV because it’s no longer being used.
If someone turns off the TV while others are still watching it, there would be
an uproar from the remaining TV watchers!
We use the `Rc<T>` type when we want to allocate some data on the heap for
multiple parts of our program to read and we can’t determine at compile time
which part will finish using the data last. If we knew which part would finish
last, we could just make that part the data’s owner, and the normal ownership
rules enforced at compile time would take effect.
Note that `Rc<T>` is only for use in single-threaded scenarios. When we discuss
concurrency in Chapter 16, we’ll cover how to do reference counting in
multithreaded programs.

`Rc<T>`, the Reference Counted Smart Pointer


The Rust Programming Language › `Rc<T>`, the Reference-Counted Smart Pointer › Sharing Data

Let’s return to our cons list example in Listing 15-5. Recall that we defined
it using `Box<T>`. This time, we’ll create two lists that both share ownership
of a third list. Conceptually, this looks similar to Figure 15-3.
<img alt="A linked list with the label 'a' pointing to three elements. The first element contains the integer 5 and points to the second element. Th
e second element contains the integer 10 and points to the third element. The third element contains the value 'Nil' that signifies the end of the l
ist; it does not point anywhere. A linked list with the label 'b' points to an element that contains the integer 3 and points to the first element o
f list 'a'. A linked list with the label 'c' points to an element that contains the integer 4 and also points to the first element of list 'a' so th
at the tails of lists 'b' and 'c' are both list 'a'." src="img/trpl15-03.svg" class="center" />
Figure 15-3: Two lists, `b` and `c`, sharing ownership of
a third list, `a`
We’ll create list `a` that contains `5` and then `10`. Then, we’ll make two
more lists: `b` that starts with `3` and `c` that starts with `4`. Both the `b`
and `c` lists will then continue on to the first `a` list containing `5` and
`10`. In other 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.


The Rust Programming Language › `Rc<T>`, the Reference-Counted Smart Pointer › Sharing Data

Listing 15-17 (src/main.rs)
```rust,ignore,does_not_compile
enum List {
    Cons(i32, Box<List>),
    Nil,
}

use crate::List::{Cons, Nil};

fn main() {
    let a = Cons(5, Box::new(Cons(10, Box::new(Nil))));
    let b = Cons(3, Box::new(a));
    let c = Cons(4, Box::new(a));
}
```
When we compile this code, we get this error:
```console
$ cargo run
   Compiling cons-list v0.1.0 (file:///projects/cons-list)
error[E0382]: use of moved value: `a`
  --> src/main.rs:11:30
   |
 9 |     let a = Cons(5, Box::new(Cons(10, Box::new(Nil))));
   |         - move occurs because `a` has type `List`, which does not implement the `Copy` trait
10 |     let b = Cons(3, Box::new(a));
   |                              - value moved here
11 |     let c = Cons(4, Box::new(a));
   |                              ^ value used here after move
   |
note: if `List` implemented `Clone`, you could clone the value
  --> src/main.rs:1:1
   |
 1 | enum List {
   | ^^^^^^^^^ consider implementing `Clone` for this type
...
10 |     let b = Cons(3, Box::new(a));
   |                              - you could clone this value

For more information about this error, try `rustc --explain E0382`.
error: could not compile `cons-list` (bin "cons-list") due to 1 previous error
```


The Rust Programming Language › `Rc<T>`, the Reference-Counted Smart Pointer › Sharing Data

The `Cons` variants own the data they hold, so when we create the `b` list, `a`
is moved into `b` and `b` owns `a`. Then, when we try to use `a` again when
creating `c`, we’re not allowed to because `a` has been moved.
We could change the definition of `Cons` to hold references instead, but then
we would have to specify lifetime parameters. By specifying lifetime
parameters, we would be specifying that every element in the list will live at
least as long as the entire list. This is the case for the elements and lists
in Listing 15-17, but not in every scenario.
Instead, we’ll change our definition of `List` to use `Rc<T>` in place of
`Box<T>`, as shown in Listing 15-18. Each `Cons` variant will now hold a value
and an `Rc<T>` pointing to a `List`. When we create `b`, instead of taking
ownership of `a`, we’ll clone the `Rc<List>` that `a` is holding, thereby
increasing the number of references from one to two and letting `a` and `b`
share ownership of the data in that `Rc<List>`. We’ll also clone `a` when
creating `c`, increasing the number of references from two to three. Every time
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.
Listing 15-18 (src/main.rs)


The Rust Programming Language › `Rc<T>`, the Reference-Counted Smart Pointer › Sharing Data

```rust
enum List {
    Cons(i32, Rc<List>),
    Nil,
}

use crate::List::{Cons, Nil};
use std::rc::Rc;

fn main() {
    let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
    let b = Cons(3, Rc::clone(&a));
    let c = Cons(4, Rc::clone(&a));
}
```
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 a new `Rc<List>` in `a`. Then, when we create `b` and `c`, we call the
`Rc::clone` function and pass a reference to the `Rc<List>` in `a` as an
argument.
We could have called `a.clone()` rather than `Rc::clone(&a)`, but Rust’s
convention is to use `Rc::clone` in this case. The implementation of
`Rc::clone` doesn’t make a deep copy of all the data like most types’
implementations of `clone` do. The call to `Rc::clone` only increments the
reference count, which doesn’t take much time. Deep copies of data can take a
lot of time. By using `Rc::clone` for reference counting, we can visually
distinguish between the deep-copy kinds of clones and the kinds of clones that
increase the reference count. When looking for performance problems in the
code, we only need to consider the deep-copy clones and can disregard calls to
`Rc::clone`.


The Rust Programming Language › `Rc<T>`, the Reference-Counted Smart Pointer › Cloning to Increase the Reference Count

Let’s change our working example in Listing 15-18 so that we can see the
reference counts changing as we create and drop references to the `Rc<List>` in
`a`.
In Listing 15-19, we’ll change `main` so that it has an inner scope around list
`c`; then, we can see how the reference count changes when `c` goes out of
scope.
Listing 15-19: Printing the reference count (src/main.rs)
```rust
// --snip--

fn main() {
    let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
    println!("count after creating a = {}", Rc::strong_count(&a));
    let b = Cons(3, Rc::clone(&a));
    println!("count after creating b = {}", Rc::strong_count(&a));
    {
        let c = Cons(4, Rc::clone(&a));
        println!("count after creating c = {}", Rc::strong_count(&a));
    }
    println!("count after c goes out of scope = {}", Rc::strong_count(&a));
}
```
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
function is named `strong_count` rather than `count` because the `Rc<T>` type
also has a `weak_count`; we’ll see what `weak_count` is used for in “Preventing
Reference Cycles Using `Weak<T>`”.
This code prints the following:


The Rust Programming Language › `Rc<T>`, the Reference-Counted Smart Pointer › Cloning to Increase the Reference Count

```console
$ cargo run
   Compiling cons-list v0.1.0 (file:///projects/cons-list)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.45s
     Running `target/debug/cons-list`
count after creating a = 1
count after creating b = 2
count after creating c = 3
count after c goes out of scope = 2
```
We can see that the `Rc<List>` in `a` has an initial reference count of 1;
then, each time we call `clone`, the count goes up by 1. When `c` goes out of
scope, the count goes down by 1. We don’t have to call a function to decrease
the reference count like we have to call `Rc::clone` to increase the reference
count: The implementation of the `Drop` trait decreases the reference count
automatically when an `Rc<T>` value goes out of scope.
What we can’t see in this example is that when `b` and then `a` go out of scope
at the end of `main`, the count is 0, and the `Rc<List>` is cleaned up
completely. Using `Rc<T>` allows a single value to have multiple owners, and
the count ensures that the value remains valid as long as any of the owners
still exist.


The Rust Programming Language › `Rc<T>`, the Reference-Counted Smart Pointer › Cloning to Increase the Reference Count

Via immutable references, `Rc<T>` allows you to share data between multiple
parts of your program for reading only. If `Rc<T>` allowed you to have multiple
mutable references too, you might violate one of the borrowing rules discussed
in Chapter 4: Multiple mutable borrows to the same place can cause data races
and inconsistencies. But being able to mutate data is very useful! In the next
section, we’ll discuss the interior mutability pattern and the `RefCell<T>`
type that you can use in conjunction with an `Rc<T>` to work with this
immutability restriction.


The Rust Programming Language › `RefCell<T>` and the Interior Mutability Pattern

_Interior mutability_ is a design pattern in Rust that allows you to mutate
data even when there are immutable references to that data; normally, this
action is disallowed by the borrowing rules. To mutate data, the pattern uses
`unsafe` code inside a data structure to bend Rust’s usual rules that govern
mutation and borrowing. Unsafe code indicates to the compiler that we’re
checking the rules manually instead of relying on the compiler to check them
for us; we will discuss unsafe code more in Chapter 20.
We can use types that use the interior mutability pattern only when we can
ensure that the borrowing rules will be followed at runtime, even though the
compiler can’t guarantee that. The `unsafe` code involved is then wrapped in a
safe API, and the outer type is still immutable.
Let’s explore this concept by looking at the `RefCell<T>` type that follows the
interior mutability pattern.


The Rust Programming Language › `RefCell<T>` and the Interior Mutability Pattern › Enforcing Borrowing Rules at Runtime

Unlike `Rc<T>`, the `RefCell<T>` type represents single ownership over the data
it holds. So, what makes `RefCell<T>` different from a type like `Box<T>`?
Recall the borrowing rules you learned in Chapter 4:
- At any given time, you can have _either_ one mutable reference or any number
  of immutable references (but not both).
- References must always be valid.
With references and `Box<T>`, the borrowing rules’ invariants are enforced at
compile time. With `RefCell<T>`, these invariants are enforced _at runtime_.
With references, if you break these rules, you’ll get a compiler error. With
`RefCell<T>`, if you break these rules, your program will panic and exit.
The advantages of checking the borrowing rules at compile time are that errors
will be caught sooner in the development process, and there is no impact on
runtime performance because all the analysis is completed beforehand. For those
reasons, checking the borrowing rules at compile time is the best choice in the
majority of cases, which is why this is Rust’s default.
The advantage of checking the borrowing rules at runtime instead is that
certain memory-safe scenarios are then allowed, where they would’ve been
disallowed by the compile-time checks. Static analysis, like the Rust compiler,
is inherently conservative. Some properties of code are impossible to detect by
analyzing the code: The most famous example is the Halting Problem, which is
beyond the scope of this book but is an interesting topic to research.


The Rust Programming Language › `RefCell<T>` and the Interior Mutability Pattern › Enforcing Borrowing Rules at Runtime

Because some analysis is impossible, if the Rust compiler can’t be sure the
code complies with the ownership rules, it might reject a correct program; in
this way, it’s conservative. If Rust accepted an incorrect program, users
wouldn’t be able to trust the guarantees Rust makes. However, if Rust rejects a
correct program, the programmer will be inconvenienced, but nothing
catastrophic can occur. The `RefCell<T>` type is useful when you’re sure your
code follows the borrowing rules but the compiler is unable to understand and
guarantee that.
Similar to `Rc<T>`, `RefCell<T>` is only for use in single-threaded scenarios
and will give you a compile-time error if you try using it in a multithreaded
context. We’ll talk about how to get the functionality of `RefCell<T>` in a
multithreaded program in Chapter 16.
Here is a recap of the reasons to choose `Box<T>`, `Rc<T>`, or `RefCell<T>`:
- `Rc<T>` enables multiple owners of the same data; `Box<T>` and `RefCell<T>`
  have single owners.
- `Box<T>` allows immutable or mutable borrows checked at compile time; `Rc<T>`
  allows only immutable borrows checked at compile time; `RefCell<T>` allows
  immutable or mutable borrows checked at runtime.
- Because `RefCell<T>` allows mutable borrows checked at runtime, you can
  mutate the value inside the `RefCell<T>` even when the `RefCell<T>` is
  immutable.
Mutating the value inside an immutable value is the interior mutability
pattern. Let’s look at a situation in which interior mutability is useful and
examine how it’s possible.


The Rust Programming Language › `RefCell<T>` and the Interior Mutability Pattern › Using Interior Mutability › Testing with Mock Objects

A consequence of the borrowing rules is that when you have an immutable value,
you can’t borrow it mutably. For example, this code won’t compile:
```rust,ignore,does_not_compile
fn main() {
    let x = 5;
    let y = &mut x;
}
```
If you tried to compile this code, you’d get the following error:
```console
$ cargo run
   Compiling borrowing v0.1.0 (file:///projects/borrowing)
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
 --> src/main.rs:3:13
  |
3 |     let y = &mut x;
  |             ^^^^^^ cannot borrow as mutable
  |
help: consider changing this to be mutable
  |
2 |     let mut x = 5;
  |         +++

For more information about this error, try `rustc --explain E0596`.
error: could not compile `borrowing` (bin "borrowing") due to 1 previous error
```
However, there are situations in which it would be useful for a value to mutate
itself in its methods but appear immutable to other code. Code outside the
value’s methods would not be able to mutate the value. Using `RefCell<T>` is
one way to get the ability to have interior mutability, but `RefCell<T>`
doesn’t get around the borrowing rules completely: The borrow checker in the
compiler allows this interior mutability, and the borrowing rules are checked
at runtime instead. If you violate the rules, you’ll get a `panic!` instead of
a compiler error.
Let’s work through a practical example where we can use `RefCell<T>` to mutate
an immutable value and see why that is useful.


The Rust Programming Language › `RefCell<T>` and the Interior Mutability Pattern › Using Interior Mutability › Testing with Mock Objects

Sometimes during testing a programmer will use a type in place of another type,
in order to observe particular behavior and assert that it’s implemented
correctly. This placeholder type is called a _test double_. Think of it in the
sense of a stunt double in filmmaking, where a person steps in and substitutes
for an actor to do a particularly tricky scene. Test doubles stand in for other
types when we’re running tests. _Mock objects_ are specific types of test
doubles that record what happens during a test so that you can assert that the
correct actions took place.
Rust doesn’t have objects in the same sense as other languages have objects,
and Rust doesn’t have mock object functionality built into the standard library
as some other languages do. However, you can definitely create a struct that
will serve the same purposes as a mock object.
Here’s the scenario we’ll test: We’ll create a library that tracks a value
against a maximum value and sends messages based on how close to the maximum
value the current value is. This library could be used to keep track of a
user’s quota for the number of API calls they’re allowed to make, for example.
Our library will only provide the functionality of tracking how close to the
maximum a value is and what the messages should be at what times. Applications
that use our library will be expected to provide the mechanism for sending the
messages: The application could show the message to the user directly, send an
email, send a text message, or do something else. The library doesn’t need to
know that detail. All it needs is something that implements a trait we’ll
provide, called `Messenger`. Listing 15-20 shows the library code.
Listing 15-20: A library to keep track of how close a value is to a maximum value and warn when the value is at certain levels (src/lib.rs)


The Rust Programming Language › `RefCell<T>` and the Interior Mutability Pattern › Using Interior Mutability › Testing with Mock Objects

```rust,noplayground
pub trait Messenger {
    fn send(&self, msg: &str);
}

pub struct LimitTracker<'a, T: Messenger> {
    messenger: &'a T,
    value: usize,
    max: usize,
}

impl<'a, T> LimitTracker<'a, T>
where
    T: Messenger,
{
    pub fn new(messenger: &'a T, max: usize) -> LimitTracker<'a, T> {
        LimitTracker {
            messenger,
            value: 0,
            max,
        }
    }

    pub fn set_value(&mut self, value: usize) {
        self.value = value;

        let percentage_of_max = self.value as f64 / self.max as f64;

        if percentage_of_max >= 1.0 {
            self.messenger.send("Error: You are over your quota!");
        } else if percentage_of_max >= 0.9 {
            self.messenger
                .send("Urgent warning: You've used up over 90% of your quota!");
        } else if percentage_of_max >= 0.75 {
            self.messenger
                .send("Warning: You've used up over 75% of your quota!");
        }
    }
}
```