feat: added cleanscript

This commit is contained in:
2026-06-22 21:27:36 +05:30
parent dbddc0ce2d
commit 4581eea409
309 changed files with 14551 additions and 46035 deletions

View File

@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Advanced Features</title>
</head>
<body>
<h1 id="advanced-features"><a class="header" href="#advanced-features">Advanced Features</a></h1>
<p>By now, youve learned the most commonly used parts of the Rust programming
language. Before we do one more project, in Chapter 21, well look at a few
aspects of the language you might run into every once in a while but may not
use every day. You can use this chapter as a reference for when you encounter
any unknowns. The features covered here are useful in very specific situations.
Although you might not reach for them often, we want to make sure you have a
grasp of all the features Rust has to offer.</p>
<p>In this chapter, well cover:</p>
<ul>
<li>Unsafe Rust: How to opt out of some of Rusts guarantees and take
responsibility for manually upholding those guarantees</li>
<li>Advanced traits: Associated types, default type parameters, fully qualified
syntax, supertraits, and the newtype pattern in relation to traits</li>
<li>Advanced types: More about the newtype pattern, type aliases, the never type,
and dynamically sized types</li>
<li>Advanced functions and closures: Function pointers and returning closures</li>
<li>Macros: Ways to define code that defines more code at compile time</li>
</ul>
<p>Its a panoply of Rust features with something for everyone! Lets dive in!</p>
</body>
</html>

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Redirecting...</title>
</head>
<body>
<p>Redirecting to... <a href="../ch21/ch21-00-final-project-a-web-server.html">ch21-00-final-project-a-web-server.html</a>.</p>
</body>
</html>

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Redirecting...</title>
</head>
<body>
<p>Redirecting to... <a href="../ch21/ch21-01-single-threaded.html">ch21-01-single-threaded.html</a>.</p>
</body>
</html>

View File

@@ -0,0 +1,606 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Unsafe Rust</title>
</head>
<body>
<h2 id="unsafe-rust"><a class="header" href="#unsafe-rust">Unsafe Rust</a></h2>
<p>All the code weve discussed so far has had Rusts memory safety guarantees
enforced at compile time. However, Rust has a second language hidden inside it
that doesnt enforce these memory safety guarantees: Its called <em>unsafe Rust</em>
and works just like regular Rust but gives us extra superpowers.</p>
<p>Unsafe Rust exists because, by nature, static analysis is conservative. When
the compiler tries to determine whether or not code upholds the guarantees,
its better for it to reject some valid programs than to accept some invalid
programs. Although the code <em>might</em> be okay, if the Rust compiler doesnt have
enough information to be confident, it will reject the code. In these cases,
you can use unsafe code to tell the compiler, “Trust me, I know what Im
doing.” Be warned, however, that you use unsafe Rust at your own risk: If you
use unsafe code incorrectly, problems can occur due to memory unsafety, such as
null pointer dereferencing.</p>
<p>Another reason Rust has an unsafe alter ego is that the underlying computer
hardware is inherently unsafe. If Rust didnt let you do unsafe operations, you
couldnt do certain tasks. Rust needs to allow you to do low-level systems
programming, such as directly interacting with the operating system or even
writing your own operating system. Working with low-level systems programming
is one of the goals of the language. Lets explore what we can do with unsafe
Rust and how to do it.</p>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="unsafe-superpowers"></a></p>
<h3 id="performing-unsafe-superpowers"><a class="header" href="#performing-unsafe-superpowers">Performing Unsafe Superpowers</a></h3>
<p>To switch to unsafe Rust, use the <code>unsafe</code> keyword and then start a new block
that holds the unsafe code. You can take five actions in unsafe Rust that you
cant in safe Rust, which we call <em>unsafe superpowers</em>. Those superpowers
include the ability to:</p>
<ol>
<li>Dereference a raw pointer.</li>
<li>Call an unsafe function or method.</li>
<li>Access or modify a mutable static variable.</li>
<li>Implement an unsafe trait.</li>
<li>Access fields of <code>union</code>s.</li>
</ol>
<p>Its important to understand that <code>unsafe</code> doesnt turn off the borrow checker
or disable any of Rusts other safety checks: If you use a reference in unsafe
code, it will still be checked. The <code>unsafe</code> keyword only gives you access to
these five features that are then not checked by the compiler for memory
safety. Youll still get some degree of safety inside an unsafe block.</p>
<p>In addition, <code>unsafe</code> does not mean the code inside the block is necessarily
dangerous or that it will definitely have memory safety problems: The intent is
that as the programmer, youll ensure that the code inside an <code>unsafe</code> block
will access memory in a valid way.</p>
<p>People are fallible and mistakes will happen, but by requiring these five
unsafe operations to be inside blocks annotated with <code>unsafe</code>, youll know that
any errors related to memory safety must be within an <code>unsafe</code> block. Keep
<code>unsafe</code> blocks small; youll be thankful later when you investigate memory
bugs.</p>
<p>To isolate unsafe code as much as possible, its best to enclose such code
within a safe abstraction and provide a safe API, which well discuss later in
the chapter when we examine unsafe functions and methods. Parts of the standard
library are implemented as safe abstractions over unsafe code that has been
audited. Wrapping unsafe code in a safe abstraction prevents uses of <code>unsafe</code>
from leaking out into all the places that you or your users might want to use
the functionality implemented with <code>unsafe</code> code, because using a safe
abstraction is safe.</p>
<p>Lets look at each of the five unsafe superpowers in turn. Well also look at
some abstractions that provide a safe interface to unsafe code.</p>
<h3 id="dereferencing-a-raw-pointer"><a class="header" href="#dereferencing-a-raw-pointer">Dereferencing a Raw Pointer</a></h3>
<p>In Chapter 4, in the <a href="../ch04/ch04-02-references-and-borrowing.html#dangling-references">“Dangling References”</a><!-- ignore
--> section, we mentioned that the compiler ensures that references are always
valid. Unsafe Rust has two new types called <em>raw pointers</em> that are similar to
references. As with references, raw pointers can be immutable or mutable and
are written as <code>*const T</code> and <code>*mut T</code>, respectively. The asterisk isnt the
dereference operator; its part of the type name. In the context of raw
pointers, <em>immutable</em> means that the pointer cant be directly assigned to
after being dereferenced.</p>
<p>Different from references and smart pointers, raw pointers:</p>
<ul>
<li>Are allowed to ignore the borrowing rules by having both immutable and
mutable pointers or multiple mutable pointers to the same location</li>
<li>Arent guaranteed to point to valid memory</li>
<li>Are allowed to be null</li>
<li>Dont implement any automatic cleanup</li>
</ul>
<p>By opting out of having Rust enforce these guarantees, you can give up
guaranteed safety in exchange for greater performance or the ability to
interface with another language or hardware where Rusts guarantees dont apply.</p>
<p>Listing 20-1 shows how to create an immutable and a mutable raw pointer.</p>
<figure class="listing" id="listing-20-1">
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
</span> let mut num = 5;
let r1 = &amp;raw const num;
let r2 = &amp;raw mut num;
<span class="boring">}</span></code></pre>
<figcaption><a href="#listing-20-1">Listing 20-1</a>: Creating raw pointers with the raw borrow operators</figcaption>
</figure>
<p>Notice that we dont include the <code>unsafe</code> keyword in this code. We can create
raw pointers in safe code; we just cant dereference raw pointers outside an
unsafe block, as youll see in a bit.</p>
<p>Weve created raw pointers by using the raw borrow operators: <code>&amp;raw const num</code>
creates a <code>*const i32</code> immutable raw pointer, and <code>&amp;raw mut num</code> creates a <code>*mut i32</code> mutable raw pointer. Because we created them directly from a local
variable, we know these particular raw pointers are valid, but we cant make
that assumption about just any raw pointer.</p>
<p>To demonstrate this, next well create a raw pointer whose validity we cant be
so certain of, using the keyword <code>as</code> to cast a value instead of using the raw
borrow operator. Listing 20-2 shows how to create a raw pointer to an arbitrary
location in memory. Trying to use arbitrary memory is undefined: There might be
data at that address or there might not, the compiler might optimize the code
so that there is no memory access, or the program might terminate with a
segmentation fault. Usually, there is no good reason to write code like this,
especially in cases where you can use a raw borrow operator instead, but it is
possible.</p>
<figure class="listing" id="listing-20-2">
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
</span> let address = 0x012345usize;
let r = address as *const i32;
<span class="boring">}</span></code></pre>
<figcaption><a href="#listing-20-2">Listing 20-2</a>: Creating a raw pointer to an arbitrary memory address</figcaption>
</figure>
<p>Recall that we can create raw pointers in safe code, but we cant dereference
raw pointers and read the data being pointed to. In Listing 20-3, we use the
dereference operator <code>*</code> on a raw pointer that requires an <code>unsafe</code> block.</p>
<figure class="listing" id="listing-20-3">
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
</span> let mut num = 5;
let r1 = &amp;raw const num;
let r2 = &amp;raw mut num;
unsafe {
println!("r1 is: {}", *r1);
println!("r2 is: {}", *r2);
}
<span class="boring">}</span></code></pre>
<figcaption><a href="#listing-20-3">Listing 20-3</a>: Dereferencing raw pointers within an <code>unsafe</code> block</figcaption>
</figure>
<p>Creating a pointer does no harm; its only when we try to access the value that
it points at that we might end up dealing with an invalid value.</p>
<p>Note also that in Listings 20-1 and 20-3, we created <code>*const i32</code> and <code>*mut i32</code> raw pointers that both pointed to the same memory location, where <code>num</code> is
stored. If we instead tried to create an immutable and a mutable reference to
<code>num</code>, the code would not have compiled because Rusts ownership rules dont
allow a mutable reference at the same time as any immutable references. With
raw pointers, we can create a mutable pointer and an immutable pointer to the
same location and change data through the mutable pointer, potentially creating
a data race. Be careful!</p>
<p>With all of these dangers, why would you ever use raw pointers? One major use
case is when interfacing with C code, as youll see in the next section.
Another case is when building up safe abstractions that the borrow checker
doesnt understand. Well introduce unsafe functions and then look at an
example of a safe abstraction that uses unsafe code.</p>
<h3 id="calling-an-unsafe-function-or-method"><a class="header" href="#calling-an-unsafe-function-or-method">Calling an Unsafe Function or Method</a></h3>
<p>The second type of operation you can perform in an unsafe block is calling
unsafe functions. Unsafe functions and methods look exactly like regular
functions and methods, but they have an extra <code>unsafe</code> before the rest of the
definition. The <code>unsafe</code> keyword in this context indicates the function has
requirements we need to uphold when we call this function, because Rust cant
guarantee weve met these requirements. By calling an unsafe function within an
<code>unsafe</code> block, were saying that weve read this functions documentation and
we take responsibility for upholding the functions contracts.</p>
<p>Here is an unsafe function named <code>dangerous</code> that doesnt do anything in its
body:</p>
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
</span> unsafe fn dangerous() {}
unsafe {
dangerous();
}
<span class="boring">}</span></code></pre>
<p>We must call the <code>dangerous</code> function within a separate <code>unsafe</code> block. If we
try to call <code>dangerous</code> without the <code>unsafe</code> block, well get an error:</p>
<pre><code class="language-console">$ cargo run
Compiling unsafe-example v0.1.0 (file:///projects/unsafe-example)
error[E0133]: call to unsafe function `dangerous` is unsafe and requires unsafe block
--&gt; src/main.rs:4:5
|
4 | dangerous();
| ^^^^^^^^^^^ call to unsafe function
|
= note: consult the function's documentation for information on how to avoid undefined behavior
For more information about this error, try `rustc --explain E0133`.
error: could not compile `unsafe-example` (bin "unsafe-example") due to 1 previous error
</code></pre>
<p>With the <code>unsafe</code> block, were asserting to Rust that weve read the functions
documentation, we understand how to use it properly, and weve verified that
were fulfilling the contract of the function.</p>
<p>To perform unsafe operations in the body of an <code>unsafe</code> function, you still
need to use an <code>unsafe</code> block, just as within a regular function, and the
compiler will warn you if you forget. This helps us keep <code>unsafe</code> blocks as
small as possible, as unsafe operations may not be needed across the whole
function body.</p>
<h4 id="creating-a-safe-abstraction-over-unsafe-code"><a class="header" href="#creating-a-safe-abstraction-over-unsafe-code">Creating a Safe Abstraction over Unsafe Code</a></h4>
<p>Just because a function contains unsafe code doesnt mean we need to mark the
entire function as unsafe. In fact, wrapping unsafe code in a safe function is
a common abstraction. As an example, lets study the <code>split_at_mut</code> function
from the standard library, which requires some unsafe code. Well explore how
we might implement it. This safe method is defined on mutable slices: It takes
one slice and makes it two by splitting the slice at the index given as an
argument. Listing 20-4 shows how to use <code>split_at_mut</code>.</p>
<figure class="listing" id="listing-20-4">
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
</span> let mut v = vec![1, 2, 3, 4, 5, 6];
let r = &amp;mut v[..];
let (a, b) = r.split_at_mut(3);
assert_eq!(a, &amp;mut [1, 2, 3]);
assert_eq!(b, &amp;mut [4, 5, 6]);
<span class="boring">}</span></code></pre>
<figcaption><a href="#listing-20-4">Listing 20-4</a>: Using the safe <code>split_at_mut</code> function</figcaption>
</figure>
<p>We cant implement this function using only safe Rust. An attempt might look
something like Listing 20-5, which wont compile. For simplicity, well
implement <code>split_at_mut</code> as a function rather than a method and only for slices
of <code>i32</code> values rather than for a generic type <code>T</code>.</p>
<figure class="listing" id="listing-20-5">
<pre><code class="language-rust ignore does_not_compile">fn split_at_mut(values: &amp;mut [i32], mid: usize) -&gt; (&amp;mut [i32], &amp;mut [i32]) {
let len = values.len();
assert!(mid &lt;= len);
(&amp;mut values[..mid], &amp;mut values[mid..])
}
<span class="boring">
</span><span class="boring">fn main() {
</span><span class="boring"> let mut vector = vec![1, 2, 3, 4, 5, 6];
</span><span class="boring"> let (left, right) = split_at_mut(&amp;mut vector, 3);
</span><span class="boring">}</span></code></pre>
<figcaption><a href="#listing-20-5">Listing 20-5</a>: An attempted implementation of <code>split_at_mut</code> using only safe Rust</figcaption>
</figure>
<p>This function first gets the total length of the slice. Then, it asserts that
the index given as a parameter is within the slice by checking whether its
less than or equal to the length. The assertion means that if we pass an index
that is greater than the length to split the slice at, the function will panic
before it attempts to use that index.</p>
<p>Then, we return two mutable slices in a tuple: one from the start of the
original slice to the <code>mid</code> index and another from <code>mid</code> to the end of the
slice.</p>
<p>When we try to compile the code in Listing 20-5, well get an error:</p>
<pre><code class="language-console">$ cargo run
Compiling unsafe-example v0.1.0 (file:///projects/unsafe-example)
error[E0499]: cannot borrow `*values` as mutable more than once at a time
--&gt; src/main.rs:6:31
|
1 | fn split_at_mut(values: &amp;mut [i32], mid: usize) -&gt; (&amp;mut [i32], &amp;mut [i32]) {
| - let's call the lifetime of this reference `'1`
...
6 | (&amp;mut values[..mid], &amp;mut values[mid..])
| --------------------------^^^^^^--------
| | | |
| | | second mutable borrow occurs here
| | first mutable borrow occurs here
| returning this value requires that `*values` is borrowed for `'1`
|
= help: use `.split_at_mut(position)` to obtain two mutable non-overlapping sub-slices
For more information about this error, try `rustc --explain E0499`.
error: could not compile `unsafe-example` (bin "unsafe-example") due to 1 previous error
</code></pre>
<p>Rusts borrow checker cant understand that were borrowing different parts of
the slice; it only knows that were borrowing from the same slice twice.
Borrowing different parts of a slice is fundamentally okay because the two
slices arent overlapping, but Rust isnt smart enough to know this. When we
know code is okay, but Rust doesnt, its time to reach for unsafe code.</p>
<p>Listing 20-6 shows how to use an <code>unsafe</code> block, a raw pointer, and some calls
to unsafe functions to make the implementation of <code>split_at_mut</code> work.</p>
<figure class="listing" id="listing-20-6">
<pre class="playground"><code class="language-rust edition2024">use std::slice;
fn split_at_mut(values: &amp;mut [i32], mid: usize) -&gt; (&amp;mut [i32], &amp;mut [i32]) {
let len = values.len();
let ptr = values.as_mut_ptr();
assert!(mid &lt;= len);
unsafe {
(
slice::from_raw_parts_mut(ptr, mid),
slice::from_raw_parts_mut(ptr.add(mid), len - mid),
)
}
}
<span class="boring">
</span><span class="boring">fn main() {
</span><span class="boring"> let mut vector = vec![1, 2, 3, 4, 5, 6];
</span><span class="boring"> let (left, right) = split_at_mut(&amp;mut vector, 3);
</span><span class="boring">}</span></code></pre>
<figcaption><a href="#listing-20-6">Listing 20-6</a>: Using unsafe code in the implementation of the <code>split_at_mut</code> function</figcaption>
</figure>
<p>Recall from <a href="../ch04/ch04-03-slices.html#the-slice-type">“The Slice Type”</a><!-- ignore --> section in
Chapter 4 that a slice is a pointer to some data and the length of the slice.
We use the <code>len</code> method to get the length of a slice and the <code>as_mut_ptr</code>
method to access the raw pointer of a slice. In this case, because we have a
mutable slice to <code>i32</code> values, <code>as_mut_ptr</code> returns a raw pointer with the type
<code>*mut i32</code>, which weve stored in the variable <code>ptr</code>.</p>
<p>We keep the assertion that the <code>mid</code> index is within the slice. Then, we get to
the unsafe code: The <code>slice::from_raw_parts_mut</code> function takes a raw pointer
and a length, and it creates a slice. We use this function to create a slice
that starts from <code>ptr</code> and is <code>mid</code> items long. Then, we call the <code>add</code> method
on <code>ptr</code> with <code>mid</code> as an argument to get a raw pointer that starts at <code>mid</code>,
and we create a slice using that pointer and the remaining number of items
after <code>mid</code> as the length.</p>
<p>The function <code>slice::from_raw_parts_mut</code> is unsafe because it takes a raw
pointer and must trust that this pointer is valid. The <code>add</code> method on raw
pointers is also unsafe because it must trust that the offset location is also
a valid pointer. Therefore, we had to put an <code>unsafe</code> block around our calls to
<code>slice::from_raw_parts_mut</code> and <code>add</code> so that we could call them. By looking at
the code and by adding the assertion that <code>mid</code> must be less than or equal to
<code>len</code>, we can tell that all the raw pointers used within the <code>unsafe</code> block
will be valid pointers to data within the slice. This is an acceptable and
appropriate use of <code>unsafe</code>.</p>
<p>Note that we dont need to mark the resultant <code>split_at_mut</code> function as
<code>unsafe</code>, and we can call this function from safe Rust. Weve created a safe
abstraction to the unsafe code with an implementation of the function that uses
<code>unsafe</code> code in a safe way, because it creates only valid pointers from the
data this function has access to.</p>
<p>In contrast, the use of <code>slice::from_raw_parts_mut</code> in Listing 20-7 would
likely crash when the slice is used. This code takes an arbitrary memory
location and creates a slice 10,000 items long.</p>
<figure class="listing" id="listing-20-7">
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
</span> use std::slice;
let address = 0x01234usize;
let r = address as *mut i32;
let values: &amp;[i32] = unsafe { slice::from_raw_parts_mut(r, 10000) };
<span class="boring">}</span></code></pre>
<figcaption><a href="#listing-20-7">Listing 20-7</a>: Creating a slice from an arbitrary memory location</figcaption>
</figure>
<p>We dont own the memory at this arbitrary location, and there is no guarantee
that the slice this code creates contains valid <code>i32</code> values. Attempting to use
<code>values</code> as though its a valid slice results in undefined behavior.</p>
<h4 id="using-extern-functions-to-call-external-code"><a class="header" href="#using-extern-functions-to-call-external-code">Using <code>extern</code> Functions to Call External Code</a></h4>
<p>Sometimes your Rust code might need to interact with code written in another
language. For this, Rust has the keyword <code>extern</code> that facilitates the creation
and use of a <em>Foreign Function Interface (FFI)</em>, which is a way for a
programming language to define functions and enable a different (foreign)
programming language to call those functions.</p>
<p>Listing 20-8 demonstrates how to set up an integration with the <code>abs</code> function
from the C standard library. Functions declared within <code>extern</code> blocks are
generally unsafe to call from Rust code, so <code>extern</code> blocks must also be marked
<code>unsafe</code>. The reason is that other languages dont enforce Rusts rules and
guarantees, and Rust cant check them, so responsibility falls on the
programmer to ensure safety.</p>
<figure class="listing" id="listing-20-8">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024">unsafe extern "C" {
fn abs(input: i32) -&gt; i32;
}
fn main() {
unsafe {
println!("Absolute value of -3 according to C: {}", abs(-3));
}
}</code></pre>
<figcaption><a href="#listing-20-8">Listing 20-8</a>: Declaring and calling an <code>extern</code> function defined in another language</figcaption>
</figure>
<p>Within the <code>unsafe extern "C"</code> block, we list the names and signatures of
external functions from another language we want to call. The <code>"C"</code> part
defines which <em>application binary interface (ABI)</em> the external function uses:
The ABI defines how to call the function at the assembly level. The <code>"C"</code> ABI
is the most common and follows the C programming languages ABI. Information
about all the ABIs Rust supports is available in <a href="../reference/items/external-blocks.html#abi">the Rust Reference</a>.</p>
<p>Every item declared within an <code>unsafe extern</code> block is implicitly unsafe.
However, some FFI functions <em>are</em> safe to call. For example, the <code>abs</code> function
from Cs standard library does not have any memory safety considerations, and we
know it can be called with any <code>i32</code>. In cases like this, we can use the <code>safe</code>
keyword to say that this specific function is safe to call even though it is in
an <code>unsafe extern</code> block. Once we make that change, calling it no longer
requires an <code>unsafe</code> block, as shown in Listing 20-9.</p>
<figure class="listing" id="listing-20-9">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024">unsafe extern "C" {
safe fn abs(input: i32) -&gt; i32;
}
fn main() {
println!("Absolute value of -3 according to C: {}", abs(-3));
}</code></pre>
<figcaption><a href="#listing-20-9">Listing 20-9</a>: Explicitly marking a function as <code>safe</code> within an <code>unsafe extern</code> block and calling it safely</figcaption>
</figure>
<p>Marking a function as <code>safe</code> does not inherently make it safe! Instead, it is
like a promise you are making to Rust that it is safe. It is still your
responsibility to make sure that promise is kept!</p>
<h4 id="calling-rust-functions-from-other-languages"><a class="header" href="#calling-rust-functions-from-other-languages">Calling Rust Functions from Other Languages</a></h4>
<p>We can also use <code>extern</code> to create an interface that allows other languages to
call Rust functions. Instead of creating a whole <code>extern</code> block, we add the
<code>extern</code> keyword and specify the ABI to use just before the <code>fn</code> keyword for
the relevant function. We also need to add an <code>#[unsafe(no_mangle)]</code> annotation
to tell the Rust compiler not to mangle the name of this function. <em>Mangling</em>
is when a compiler changes the name weve given a function to a different name
that contains more information for other parts of the compilation process to
consume but is less human readable. Every programming language compiler mangles
names slightly differently, so for a Rust function to be nameable by other
languages, we must disable the Rust compilers name mangling. This is unsafe
because there might be name collisions across libraries without the built-in
mangling, so it is our responsibility to make sure the name we choose is safe
to export without mangling.</p>
<p>In the following example, we make the <code>call_from_c</code> function accessible from C
code, after its compiled to a shared library and linked from C:</p>
<pre><code>#[unsafe(no_mangle)]
pub extern "C" fn call_from_c() {
println!("Just called a Rust function from C!");
}
</code></pre>
<p>This usage of <code>extern</code> requires <code>unsafe</code> only in the attribute, not on the
<code>extern</code> block.</p>
<h3 id="accessing-or-modifying-a-mutable-static-variable"><a class="header" href="#accessing-or-modifying-a-mutable-static-variable">Accessing or Modifying a Mutable Static Variable</a></h3>
<p>In this book, weve not yet talked about global variables, which Rust does
support but which can be problematic with Rusts ownership rules. If two
threads are accessing the same mutable global variable, it can cause a data
race.</p>
<p>In Rust, global variables are called <em>static</em> variables. Listing 20-10 shows an
example declaration and use of a static variable with a string slice as a
value.</p>
<figure class="listing" id="listing-20-10">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024">static HELLO_WORLD: &amp;str = "Hello, world!";
fn main() {
println!("value is: {HELLO_WORLD}");
}</code></pre>
<figcaption><a href="#listing-20-10">Listing 20-10</a>: Defining and using an immutable static variable</figcaption>
</figure>
<p>Static variables are similar to constants, which we discussed in the
<a href="../ch03/ch03-01-variables-and-mutability.html#declaring-constants">“Declaring Constants”</a><!-- ignore --> section in Chapter 3. The
names of static variables are in <code>SCREAMING_SNAKE_CASE</code> by convention. Static
variables can only store references with the <code>'static</code> lifetime, which means
the Rust compiler can figure out the lifetime and we arent required to
annotate it explicitly. Accessing an immutable static variable is safe.</p>
<p>A subtle difference between constants and immutable static variables is that
values in a static variable have a fixed address in memory. Using the value
will always access the same data. Constants, on the other hand, are allowed to
duplicate their data whenever theyre used. Another difference is that static
variables can be mutable. Accessing and modifying mutable static variables is
<em>unsafe</em>. Listing 20-11 shows how to declare, access, and modify a mutable
static variable named <code>COUNTER</code>.</p>
<figure class="listing" id="listing-20-11">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024">static mut COUNTER: u32 = 0;
/// SAFETY: Calling this from more than a single thread at a time is undefined
/// behavior, so you *must* guarantee you only call it from a single thread at
/// a time.
unsafe fn add_to_count(inc: u32) {
unsafe {
COUNTER += inc;
}
}
fn main() {
unsafe {
// SAFETY: This is only called from a single thread in `main`.
add_to_count(3);
println!("COUNTER: {}", *(&amp;raw const COUNTER));
}
}</code></pre>
<figcaption><a href="#listing-20-11">Listing 20-11</a>: Reading from or writing to a mutable static variable is unsafe.</figcaption>
</figure>
<p>As with regular variables, we specify mutability using the <code>mut</code> keyword. Any
code that reads or writes from <code>COUNTER</code> must be within an <code>unsafe</code> block. The
code in Listing 20-11 compiles and prints <code>COUNTER: 3</code> as we would expect
because its single threaded. Having multiple threads access <code>COUNTER</code> would
likely result in data races, so it is undefined behavior. Therefore, we need to
mark the entire function as <code>unsafe</code> and document the safety limitation so that
anyone calling the function knows what they are and are not allowed to do
safely.</p>
<p>Whenever we write an unsafe function, it is idiomatic to write a comment
starting with <code>SAFETY</code> and explaining what the caller needs to do to call the
function safely. Likewise, whenever we perform an unsafe operation, it is
idiomatic to write a comment starting with <code>SAFETY</code> to explain how the safety
rules are upheld.</p>
<p>Additionally, the compiler will deny by default any attempt to create
references to a mutable static variable through a compiler lint. You must
either explicitly opt out of that lints protections by adding an
<code>#[allow(static_mut_refs)]</code> annotation or access the mutable static variable
via a raw pointer created with one of the raw borrow operators. That includes
cases where the reference is created invisibly, as when it is used in the
<code>println!</code> in this code listing. Requiring references to static mutable
variables to be created via raw pointers helps make the safety requirements for
using them more obvious.</p>
<p>With mutable data that is globally accessible, its difficult to ensure that
there are no data races, which is why Rust considers mutable static variables
to be unsafe. Where possible, its preferable to use the concurrency techniques
and thread-safe smart pointers we discussed in Chapter 16 so that the compiler
checks that data access from different threads is done safely.</p>
<h3 id="implementing-an-unsafe-trait"><a class="header" href="#implementing-an-unsafe-trait">Implementing an Unsafe Trait</a></h3>
<p>We can use <code>unsafe</code> to implement an unsafe trait. A trait is unsafe when at
least one of its methods has some invariant that the compiler cant verify. We
declare that a trait is <code>unsafe</code> by adding the <code>unsafe</code> keyword before <code>trait</code>
and marking the implementation of the trait as <code>unsafe</code> too, as shown in
Listing 20-12.</p>
<figure class="listing" id="listing-20-12">
<pre class="playground"><code class="language-rust edition2024">unsafe trait Foo {
// methods go here
}
unsafe impl Foo for i32 {
// method implementations go here
}
<span class="boring">
</span><span class="boring">fn main() {}</span></code></pre>
<figcaption><a href="#listing-20-12">Listing 20-12</a>: Defining and implementing an unsafe trait</figcaption>
</figure>
<p>By using <code>unsafe impl</code>, were promising that well uphold the invariants that
the compiler cant verify.</p>
<p>As an example, recall the <code>Send</code> and <code>Sync</code> marker traits we discussed in the
<a href="../ch16/ch16-04-extensible-concurrency-sync-and-send.html">“Extensible Concurrency with <code>Send</code> and <code>Sync</code></a><!-- ignore -->
section in Chapter 16: The compiler implements these traits automatically if
our types are composed entirely of other types that implement <code>Send</code> and
<code>Sync</code>. If we implement a type that contains a type that does not implement
<code>Send</code> or <code>Sync</code>, such as raw pointers, and we want to mark that type as <code>Send</code>
or <code>Sync</code>, we must use <code>unsafe</code>. Rust cant verify that our type upholds the
guarantees that it can be safely sent across threads or accessed from multiple
threads; therefore, we need to do those checks manually and indicate as such
with <code>unsafe</code>.</p>
<h3 id="accessing-fields-of-a-union"><a class="header" href="#accessing-fields-of-a-union">Accessing Fields of a Union</a></h3>
<p>The final action that works only with <code>unsafe</code> is accessing fields of a union.
A <em>union</em> is similar to a <code>struct</code>, but only one declared field is used in a
particular instance at one time. Unions are primarily used to interface with
unions in C code. Accessing union fields is unsafe because Rust cant guarantee
the type of the data currently being stored in the union instance. You can
learn more about unions in <a href="../reference/items/unions.html">the Rust Reference</a>.</p>
<h3 id="using-miri-to-check-unsafe-code"><a class="header" href="#using-miri-to-check-unsafe-code">Using Miri to Check Unsafe Code</a></h3>
<p>When writing unsafe code, you might want to check that what you have written
actually is safe and correct. One of the best ways to do that is to use Miri,
an official Rust tool for detecting undefined behavior. Whereas the borrow
checker is a <em>static</em> tool that works at compile time, Miri is a <em>dynamic</em>
tool that works at runtime. It checks your code by running your program, or
its test suite, and detecting when you violate the rules it understands about
how Rust should work.</p>
<p>Using Miri requires a nightly build of Rust (which we talk about more in
<a href="../appendix/appendix-07-nightly-rust.html">Appendix G: How Rust is Made and “Nightly Rust”</a><!-- ignore -->). You
can install both a nightly version of Rust and the Miri tool by typing <code>rustup +nightly component add miri</code>. This does not change what version of Rust your
project uses; it only adds the tool to your system so you can use it when you
want to. You can run Miri on a project by typing <code>cargo +nightly miri run</code> or
<code>cargo +nightly miri test</code>.</p>
<p>For an example of how helpful this can be, consider what happens when we run it
against Listing 20-7.</p>
<pre><code class="language-console">$ cargo +nightly miri run
Compiling unsafe-example v0.1.0 (file:///projects/unsafe-example)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.01s
Running `file:///home/.rustup/toolchains/nightly/bin/cargo-miri runner target/miri/debug/unsafe-example`
warning: integer-to-pointer cast
--&gt; src/main.rs:5:13
|
5 | let r = address as *mut i32;
| ^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
|
= help: this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program
= help: see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation
= help: to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead
= help: you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics
= help: alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning
= note: BACKTRACE:
= note: inside `main` at src/main.rs:5:13: 5:32
error: Undefined Behavior: pointer not dereferenceable: pointer must be dereferenceable for 40000 bytes, but got 0x1234[noalloc] which is a dangling pointer (it has no provenance)
--&gt; src/main.rs:7:35
|
7 | let values: &amp;[i32] = unsafe { slice::from_raw_parts_mut(r, 10000) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `main` at src/main.rs:7:35: 7:70
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error; 1 warning emitted
</code></pre>
<p>Miri correctly warns us that were casting an integer to a pointer, which might
be a problem, but Miri cant determine whether a problem exists because it
doesnt know how the pointer originated. Then, Miri returns an error where
Listing 20-7 has undefined behavior because we have a dangling pointer. Thanks
to Miri, we now know there is a risk of undefined behavior, and we can think
about how to make the code safe. In some cases, Miri can even make
recommendations about how to fix errors.</p>
<p>Miri doesnt catch everything you might get wrong when writing unsafe code.
Miri is a dynamic analysis tool, so it only catches problems with code that
actually gets run. That means you will need to use it in conjunction with good
testing techniques to increase your confidence about the unsafe code you have
written. Miri also does not cover every possible way your code can be unsound.</p>
<p>Put another way: If Miri <em>does</em> catch a problem, you know theres a bug, but
just because Miri <em>doesnt</em> catch a bug doesnt mean there isnt a problem. It
can catch a lot, though. Try running it on the other examples of unsafe code in
this chapter and see what it says!</p>
<p>You can learn more about Miri at <a href="https://github.com/rust-lang/miri">its GitHub repository</a>.</p>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="when-to-use-unsafe-code"></a></p>
<h3 id="using-unsafe-code-correctly"><a class="header" href="#using-unsafe-code-correctly">Using Unsafe Code Correctly</a></h3>
<p>Using <code>unsafe</code> to use one of the five superpowers just discussed isnt wrong or
even frowned upon, but it is trickier to get <code>unsafe</code> code correct because the
compiler cant help uphold memory safety. When you have a reason to use
<code>unsafe</code> code, you can do so, and having the explicit <code>unsafe</code> annotation makes
it easier to track down the source of problems when they occur. Whenever you
write unsafe code, you can use Miri to help you be more confident that the code
you have written upholds Rusts rules.</p>
<p>For a much deeper exploration of how to work effectively with unsafe Rust, read
Rusts official guide for <code>unsafe</code>, <a href="https://doc.rust-lang.org/nomicon/">The Rustonomicon</a>.</p>
</body>
</html>

View File

@@ -0,0 +1,710 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Advanced Traits</title>
</head>
<body>
<h2 id="advanced-traits"><a class="header" href="#advanced-traits">Advanced Traits</a></h2>
<p>We first covered traits in the <a href="../ch10/ch10-02-traits.html">“Defining Shared Behavior with
Traits”</a><!-- ignore --> section in Chapter 10, but we didnt discuss
the more advanced details. Now that you know more about Rust, we can get into
the nitty-gritty.</p>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="specifying-placeholder-types-in-trait-definitions-with-associated-types"></a>
<a id="associated-types"></a></p>
<h3 id="defining-traits-with-associated-types"><a class="header" href="#defining-traits-with-associated-types">Defining Traits with Associated Types</a></h3>
<p><em>Associated types</em> connect a type placeholder with a trait such that the trait
method definitions can use these placeholder types in their signatures. The
implementor of a trait will specify the concrete type to be used instead of the
placeholder type for the particular implementation. That way, we can define a
trait that uses some types without needing to know exactly what those types are
until the trait is implemented.</p>
<p>Weve described most of the advanced features in this chapter as being rarely
needed. Associated types are somewhere in the middle: Theyre used more rarely
than features explained in the rest of the book but more commonly than many of
the other features discussed in this chapter.</p>
<p>One example of a trait with an associated type is the <code>Iterator</code> trait that the
standard library provides. The associated type is named <code>Item</code> and stands in
for the type of the values the type implementing the <code>Iterator</code> trait is
iterating over. The definition of the <code>Iterator</code> trait is as shown in Listing
20-13.</p>
<figure class="listing" id="listing-20-13">
<pre><code class="language-rust noplayground">pub trait Iterator {
type Item;
fn next(&amp;mut self) -&gt; Option&lt;Self::Item&gt;;
}</code></pre>
<figcaption><a href="#listing-20-13">Listing 20-13</a>: The definition of the <code>Iterator</code> trait that has an associated type <code>Item</code></figcaption>
</figure>
<p>The type <code>Item</code> is a placeholder, and the <code>next</code> methods definition shows that
it will return values of type <code>Option&lt;Self::Item&gt;</code>. Implementors of the
<code>Iterator</code> trait will specify the concrete type for <code>Item</code>, and the <code>next</code>
method will return an <code>Option</code> containing a value of that concrete type.</p>
<p>Associated types might seem like a similar concept to generics, in that the
latter allow us to define a function without specifying what types it can
handle. To examine the difference between the two concepts, well look at an
implementation of the <code>Iterator</code> trait on a type named <code>Counter</code> that specifies
the <code>Item</code> type is <code>u32</code>:</p>
<figure class="listing">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust ignore"><span class="boring">struct Counter {
</span><span class="boring"> count: u32,
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">impl Counter {
</span><span class="boring"> fn new() -&gt; Counter {
</span><span class="boring"> Counter { count: 0 }
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span>impl Iterator for Counter {
type Item = u32;
fn next(&amp;mut self) -&gt; Option&lt;Self::Item&gt; {
// --snip--
<span class="boring"> if self.count &lt; 5 {
</span><span class="boring"> self.count += 1;
</span><span class="boring"> Some(self.count)
</span><span class="boring"> } else {
</span><span class="boring"> None
</span><span class="boring"> }
</span><span class="boring"> }
</span><span class="boring">}</span></code></pre>
</figure>
<p>This syntax seems comparable to that of generics. So, why not just define the
<code>Iterator</code> trait with generics, as shown in Listing 20-14?</p>
<figure class="listing" id="listing-20-14">
<pre><code class="language-rust noplayground">pub trait Iterator&lt;T&gt; {
fn next(&amp;mut self) -&gt; Option&lt;T&gt;;
}</code></pre>
<figcaption><a href="#listing-20-14">Listing 20-14</a>: A hypothetical definition of the <code>Iterator</code> trait using generics</figcaption>
</figure>
<p>The difference is that when using generics, as in Listing 20-14, we must
annotate the types in each implementation; because we can also implement
<code>Iterator&lt;String&gt; for Counter</code> or any other type, we could have multiple
implementations of <code>Iterator</code> for <code>Counter</code>. In other words, when a trait has a
generic parameter, it can be implemented for a type multiple times, changing
the concrete types of the generic type parameters each time. When we use the
<code>next</code> method on <code>Counter</code>, we would have to provide type annotations to
indicate which implementation of <code>Iterator</code> we want to use.</p>
<p>With associated types, we dont need to annotate types, because we cant
implement a trait on a type multiple times. In Listing 20-13 with the
definition that uses associated types, we can choose what the type of <code>Item</code>
will be only once because there can be only one <code>impl Iterator for Counter</code>. We
dont have to specify that we want an iterator of <code>u32</code> values everywhere we
call <code>next</code> on <code>Counter</code>.</p>
<p>Associated types also become part of the traits contract: Implementors of the
trait must provide a type to stand in for the associated type placeholder.
Associated types often have a name that describes how the type will be used,
and documenting the associated type in the API documentation is a good practice.</p>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="default-generic-type-parameters-and-operator-overloading"></a></p>
<h3 id="using-default-generic-parameters-and-operator-overloading"><a class="header" href="#using-default-generic-parameters-and-operator-overloading">Using Default Generic Parameters and Operator Overloading</a></h3>
<p>When we use generic type parameters, we can specify a default concrete type for
the generic type. This eliminates the need for implementors of the trait to
specify a concrete type if the default type works. You specify a default type
when declaring a generic type with the <code>&lt;PlaceholderType=ConcreteType&gt;</code> syntax.</p>
<p>A great example of a situation where this technique is useful is with <em>operator
overloading</em>, in which you customize the behavior of an operator (such as <code>+</code>)
in particular situations.</p>
<p>Rust doesnt allow you to create your own operators or overload arbitrary
operators. But you can overload the operations and corresponding traits listed
in <code>std::ops</code> by implementing the traits associated with the operator. For
example, in Listing 20-15, we overload the <code>+</code> operator to add two <code>Point</code>
instances together. We do this by implementing the <code>Add</code> trait on a <code>Point</code>
struct.</p>
<figure class="listing" id="listing-20-15">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024">use std::ops::Add;
#[derive(Debug, Copy, Clone, PartialEq)]
struct Point {
x: i32,
y: i32,
}
impl Add for Point {
type Output = Point;
fn add(self, other: Point) -&gt; Point {
Point {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
fn main() {
assert_eq!(
Point { x: 1, y: 0 } + Point { x: 2, y: 3 },
Point { x: 3, y: 3 }
);
}</code></pre>
<figcaption><a href="#listing-20-15">Listing 20-15</a>: Implementing the <code>Add</code> trait to overload the <code>+</code> operator for <code>Point</code> instances</figcaption>
</figure>
<p>The <code>add</code> method adds the <code>x</code> values of two <code>Point</code> instances and the <code>y</code>
values of two <code>Point</code> instances to create a new <code>Point</code>. The <code>Add</code> trait has an
associated type named <code>Output</code> that determines the type returned from the <code>add</code>
method.</p>
<p>The default generic type in this code is within the <code>Add</code> trait. Here is its
definition:</p>
<pre class="playground"><code class="language-rust edition2024"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>trait Add&lt;Rhs=Self&gt; {
type Output;
fn add(self, rhs: Rhs) -&gt; Self::Output;
}
<span class="boring">}</span></code></pre>
<p>This code should look generally familiar: a trait with one method and an
associated type. The new part is <code>Rhs=Self</code>: This syntax is called <em>default
type parameters</em>. The <code>Rhs</code> generic type parameter (short for “right-hand
side”) defines the type of the <code>rhs</code> parameter in the <code>add</code> method. If we dont
specify a concrete type for <code>Rhs</code> when we implement the <code>Add</code> trait, the type
of <code>Rhs</code> will default to <code>Self</code>, which will be the type were implementing
<code>Add</code> on.</p>
<p>When we implemented <code>Add</code> for <code>Point</code>, we used the default for <code>Rhs</code> because we
wanted to add two <code>Point</code> instances. Lets look at an example of implementing
the <code>Add</code> trait where we want to customize the <code>Rhs</code> type rather than using the
default.</p>
<p>We have two structs, <code>Millimeters</code> and <code>Meters</code>, holding values in different
units. This thin wrapping of an existing type in another struct is known as the
<em>newtype pattern</em>, which we describe in more detail in the <a href="ch20-02-advanced-traits.html#implementing-external-traits-with-the-newtype-pattern">“Implementing
External Traits with the Newtype Pattern”</a><!-- ignore --> section. We
want to add values in millimeters to values in meters and have the
implementation of <code>Add</code> do the conversion correctly. We can implement <code>Add</code> for
<code>Millimeters</code> with <code>Meters</code> as the <code>Rhs</code>, as shown in Listing 20-16.</p>
<figure class="listing" id="listing-20-16">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground">use std::ops::Add;
struct Millimeters(u32);
struct Meters(u32);
impl Add&lt;Meters&gt; for Millimeters {
type Output = Millimeters;
fn add(self, other: Meters) -&gt; Millimeters {
Millimeters(self.0 + (other.0 * 1000))
}
}</code></pre>
<figcaption><a href="#listing-20-16">Listing 20-16</a>: Implementing the <code>Add</code> trait on <code>Millimeters</code> to add <code>Millimeters</code> and <code>Meters</code></figcaption>
</figure>
<p>To add <code>Millimeters</code> and <code>Meters</code>, we specify <code>impl Add&lt;Meters&gt;</code> to set the
value of the <code>Rhs</code> type parameter instead of using the default of <code>Self</code>.</p>
<p>Youll use default type parameters in two main ways:</p>
<ol>
<li>To extend a type without breaking existing code</li>
<li>To allow customization in specific cases most users wont need</li>
</ol>
<p>The standard librarys <code>Add</code> trait is an example of the second purpose:
Usually, youll add two like types, but the <code>Add</code> trait provides the ability to
customize beyond that. Using a default type parameter in the <code>Add</code> trait
definition means you dont have to specify the extra parameter most of the
time. In other words, a bit of implementation boilerplate isnt needed, making
it easier to use the trait.</p>
<p>The first purpose is similar to the second but in reverse: If you want to add a
type parameter to an existing trait, you can give it a default to allow
extension of the functionality of the trait without breaking the existing
implementation code.</p>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name"></a>
<a id="disambiguating-between-methods-with-the-same-name"></a></p>
<h3 id="disambiguating-between-identically-named-methods"><a class="header" href="#disambiguating-between-identically-named-methods">Disambiguating Between Identically Named Methods</a></h3>
<p>Nothing in Rust prevents a trait from having a method with the same name as
another traits method, nor does Rust prevent you from implementing both traits
on one type. Its also possible to implement a method directly on the type with
the same name as methods from traits.</p>
<p>When calling methods with the same name, youll need to tell Rust which one you
want to use. Consider the code in Listing 20-17 where weve defined two traits,
<code>Pilot</code> and <code>Wizard</code>, that both have a method called <code>fly</code>. We then implement
both traits on a type <code>Human</code> that already has a method named <code>fly</code> implemented
on it. Each <code>fly</code> method does something different.</p>
<figure class="listing" id="listing-20-17">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024">trait Pilot {
fn fly(&amp;self);
}
trait Wizard {
fn fly(&amp;self);
}
struct Human;
impl Pilot for Human {
fn fly(&amp;self) {
println!("This is your captain speaking.");
}
}
impl Wizard for Human {
fn fly(&amp;self) {
println!("Up!");
}
}
impl Human {
fn fly(&amp;self) {
println!("*waving arms furiously*");
}
}
<span class="boring">
</span><span class="boring">fn main() {}</span></code></pre>
<figcaption><a href="#listing-20-17">Listing 20-17</a>: Two traits are defined to have a <code>fly</code> method and are implemented on the <code>Human</code> type, and a <code>fly</code> method is implemented on <code>Human</code> directly.</figcaption>
</figure>
<p>When we call <code>fly</code> on an instance of <code>Human</code>, the compiler defaults to calling
the method that is directly implemented on the type, as shown in Listing 20-18.</p>
<figure class="listing" id="listing-20-18">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024"><span class="boring">trait Pilot {
</span><span class="boring"> fn fly(&amp;self);
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">trait Wizard {
</span><span class="boring"> fn fly(&amp;self);
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">struct Human;
</span><span class="boring">
</span><span class="boring">impl Pilot for Human {
</span><span class="boring"> fn fly(&amp;self) {
</span><span class="boring"> println!("This is your captain speaking.");
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">impl Wizard for Human {
</span><span class="boring"> fn fly(&amp;self) {
</span><span class="boring"> println!("Up!");
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">impl Human {
</span><span class="boring"> fn fly(&amp;self) {
</span><span class="boring"> println!("*waving arms furiously*");
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span>fn main() {
let person = Human;
person.fly();
}</code></pre>
<figcaption><a href="#listing-20-18">Listing 20-18</a>: Calling <code>fly</code> on an instance of <code>Human</code></figcaption>
</figure>
<p>Running this code will print <code>*waving arms furiously*</code>, showing that Rust
called the <code>fly</code> method implemented on <code>Human</code> directly.</p>
<p>To call the <code>fly</code> methods from either the <code>Pilot</code> trait or the <code>Wizard</code> trait,
we need to use more explicit syntax to specify which <code>fly</code> method we mean.
Listing 20-19 demonstrates this syntax.</p>
<figure class="listing" id="listing-20-19">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024"><span class="boring">trait Pilot {
</span><span class="boring"> fn fly(&amp;self);
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">trait Wizard {
</span><span class="boring"> fn fly(&amp;self);
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">struct Human;
</span><span class="boring">
</span><span class="boring">impl Pilot for Human {
</span><span class="boring"> fn fly(&amp;self) {
</span><span class="boring"> println!("This is your captain speaking.");
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">impl Wizard for Human {
</span><span class="boring"> fn fly(&amp;self) {
</span><span class="boring"> println!("Up!");
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">impl Human {
</span><span class="boring"> fn fly(&amp;self) {
</span><span class="boring"> println!("*waving arms furiously*");
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span>fn main() {
let person = Human;
Pilot::fly(&amp;person);
Wizard::fly(&amp;person);
person.fly();
}</code></pre>
<figcaption><a href="#listing-20-19">Listing 20-19</a>: Specifying which traits <code>fly</code> method we want to call</figcaption>
</figure>
<p>Specifying the trait name before the method name clarifies to Rust which
implementation of <code>fly</code> we want to call. We could also write
<code>Human::fly(&amp;person)</code>, which is equivalent to the <code>person.fly()</code> that we used
in Listing 20-19, but this is a bit longer to write if we dont need to
disambiguate.</p>
<p>Running this code prints the following:</p>
<pre><code class="language-console">$ cargo run
Compiling traits-example v0.1.0 (file:///projects/traits-example)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.46s
Running `target/debug/traits-example`
This is your captain speaking.
Up!
*waving arms furiously*
</code></pre>
<p>Because the <code>fly</code> method takes a <code>self</code> parameter, if we had two <em>types</em> that
both implement one <em>trait</em>, Rust could figure out which implementation of a
trait to use based on the type of <code>self</code>.</p>
<p>However, associated functions that are not methods dont have a <code>self</code>
parameter. When there are multiple types or traits that define non-method
functions with the same function name, Rust doesnt always know which type you
mean unless you use fully qualified syntax. For example, in Listing 20-20, we
create a trait for an animal shelter that wants to name all baby dogs Spot. We
make an <code>Animal</code> trait with an associated non-method function <code>baby_name</code>. The
<code>Animal</code> trait is implemented for the struct <code>Dog</code>, on which we also provide an
associated non-method function <code>baby_name</code> directly.</p>
<figure class="listing" id="listing-20-20">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024">trait Animal {
fn baby_name() -&gt; String;
}
struct Dog;
impl Dog {
fn baby_name() -&gt; String {
String::from("Spot")
}
}
impl Animal for Dog {
fn baby_name() -&gt; String {
String::from("puppy")
}
}
fn main() {
println!("A baby dog is called a {}", Dog::baby_name());
}</code></pre>
<figcaption><a href="#listing-20-20">Listing 20-20</a>: A trait with an associated function and a type with an associated function of the same name that also implements the trait</figcaption>
</figure>
<p>We implement the code for naming all puppies Spot in the <code>baby_name</code> associated
function that is defined on <code>Dog</code>. The <code>Dog</code> type also implements the trait
<code>Animal</code>, which describes characteristics that all animals have. Baby dogs are
called puppies, and that is expressed in the implementation of the <code>Animal</code>
trait on <code>Dog</code> in the <code>baby_name</code> function associated with the <code>Animal</code> trait.</p>
<p>In <code>main</code>, we call the <code>Dog::baby_name</code> function, which calls the associated
function defined on <code>Dog</code> directly. This code prints the following:</p>
<pre><code class="language-console">$ cargo run
Compiling traits-example v0.1.0 (file:///projects/traits-example)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.54s
Running `target/debug/traits-example`
A baby dog is called a Spot
</code></pre>
<p>This output isnt what we wanted. We want to call the <code>baby_name</code> function that
is part of the <code>Animal</code> trait that we implemented on <code>Dog</code> so that the code
prints <code>A baby dog is called a puppy</code>. The technique of specifying the trait
name that we used in Listing 20-19 doesnt help here; if we change <code>main</code> to
the code in Listing 20-21, well get a compilation error.</p>
<figure class="listing" id="listing-20-21">
<span class="file-name">Filename: src/main.rs</span>
<pre><code class="language-rust ignore does_not_compile"><span class="boring">trait Animal {
</span><span class="boring"> fn baby_name() -&gt; String;
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">struct Dog;
</span><span class="boring">
</span><span class="boring">impl Dog {
</span><span class="boring"> fn baby_name() -&gt; String {
</span><span class="boring"> String::from("Spot")
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">impl Animal for Dog {
</span><span class="boring"> fn baby_name() -&gt; String {
</span><span class="boring"> String::from("puppy")
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span>fn main() {
println!("A baby dog is called a {}", Animal::baby_name());
}</code></pre>
<figcaption><a href="#listing-20-21">Listing 20-21</a>: Attempting to call the <code>baby_name</code> function from the <code>Animal</code> trait, but Rust doesnt know which implementation to use</figcaption>
</figure>
<p>Because <code>Animal::baby_name</code> doesnt have a <code>self</code> parameter, and there could be
other types that implement the <code>Animal</code> trait, Rust cant figure out which
implementation of <code>Animal::baby_name</code> we want. Well get this compiler error:</p>
<pre><code class="language-console">$ cargo run
Compiling traits-example v0.1.0 (file:///projects/traits-example)
error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
--&gt; src/main.rs:20:43
|
2 | fn baby_name() -&gt; String;
| ------------------------- `Animal::baby_name` defined here
...
20 | println!("A baby dog is called a {}", Animal::baby_name());
| ^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait
|
help: use the fully-qualified path to the only available implementation
|
20 | println!("A baby dog is called a {}", &lt;Dog as Animal&gt;::baby_name());
| +++++++ +
For more information about this error, try `rustc --explain E0790`.
error: could not compile `traits-example` (bin "traits-example") due to 1 previous error
</code></pre>
<p>To disambiguate and tell Rust that we want to use the implementation of
<code>Animal</code> for <code>Dog</code> as opposed to the implementation of <code>Animal</code> for some other
type, we need to use fully qualified syntax. Listing 20-22 demonstrates how to
use fully qualified syntax.</p>
<figure class="listing" id="listing-20-22">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024"><span class="boring">trait Animal {
</span><span class="boring"> fn baby_name() -&gt; String;
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">struct Dog;
</span><span class="boring">
</span><span class="boring">impl Dog {
</span><span class="boring"> fn baby_name() -&gt; String {
</span><span class="boring"> String::from("Spot")
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">impl Animal for Dog {
</span><span class="boring"> fn baby_name() -&gt; String {
</span><span class="boring"> String::from("puppy")
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span>fn main() {
println!("A baby dog is called a {}", &lt;Dog as Animal&gt;::baby_name());
}</code></pre>
<figcaption><a href="#listing-20-22">Listing 20-22</a>: Using fully qualified syntax to specify that we want to call the <code>baby_name</code> function from the <code>Animal</code> trait as implemented on <code>Dog</code></figcaption>
</figure>
<p>Were providing Rust with a type annotation within the angle brackets, which
indicates we want to call the <code>baby_name</code> method from the <code>Animal</code> trait as
implemented on <code>Dog</code> by saying that we want to treat the <code>Dog</code> type as an
<code>Animal</code> for this function call. This code will now print what we want:</p>
<pre><code class="language-console">$ cargo run
Compiling traits-example v0.1.0 (file:///projects/traits-example)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.48s
Running `target/debug/traits-example`
A baby dog is called a puppy
</code></pre>
<p>In general, fully qualified syntax is defined as follows:</p>
<pre><code class="language-rust ignore">&lt;Type as Trait&gt;::function(receiver_if_method, next_arg, ...);</code></pre>
<p>For associated functions that arent methods, there would not be a <code>receiver</code>:
There would only be the list of other arguments. You could use fully qualified
syntax everywhere that you call functions or methods. However, youre allowed
to omit any part of this syntax that Rust can figure out from other information
in the program. You only need to use this more verbose syntax in cases where
there are multiple implementations that use the same name and Rust needs help
to identify which implementation you want to call.</p>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="using-supertraits-to-require-one-traits-functionality-within-another-trait"></a></p>
<h3 id="using-supertraits"><a class="header" href="#using-supertraits">Using Supertraits</a></h3>
<p>Sometimes you might write a trait definition that depends on another trait: For
a type to implement the first trait, you want to require that type to also
implement the second trait. You would do this so that your trait definition can
make use of the associated items of the second trait. The trait your trait
definition is relying on is called a <em>supertrait</em> of your trait.</p>
<p>For example, lets say we want to make an <code>OutlinePrint</code> trait with an
<code>outline_print</code> method that will print a given value formatted so that its
framed in asterisks. That is, given a <code>Point</code> struct that implements the
standard library trait <code>Display</code> to result in <code>(x, y)</code>, when we call
<code>outline_print</code> on a <code>Point</code> instance that has <code>1</code> for <code>x</code> and <code>3</code> for <code>y</code>, it
should print the following:</p>
<pre><code class="language-text">**********
* *
* (1, 3) *
* *
**********
</code></pre>
<p>In the implementation of the <code>outline_print</code> method, we want to use the
<code>Display</code> traits functionality. Therefore, we need to specify that the
<code>OutlinePrint</code> trait will work only for types that also implement <code>Display</code> and
provide the functionality that <code>OutlinePrint</code> needs. We can do that in the
trait definition by specifying <code>OutlinePrint: Display</code>. This technique is
similar to adding a trait bound to the trait. Listing 20-23 shows an
implementation of the <code>OutlinePrint</code> trait.</p>
<figure class="listing" id="listing-20-23">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024">use std::fmt;
trait OutlinePrint: fmt::Display {
fn outline_print(&amp;self) {
let output = self.to_string();
let len = output.len();
println!("{}", "*".repeat(len + 4));
println!("*{}*", " ".repeat(len + 2));
println!("* {output} *");
println!("*{}*", " ".repeat(len + 2));
println!("{}", "*".repeat(len + 4));
}
}
<span class="boring">
</span><span class="boring">fn main() {}</span></code></pre>
<figcaption><a href="#listing-20-23">Listing 20-23</a>: Implementing the <code>OutlinePrint</code> trait that requires the functionality from <code>Display</code></figcaption>
</figure>
<p>Because weve specified that <code>OutlinePrint</code> requires the <code>Display</code> trait, we
can use the <code>to_string</code> function that is automatically implemented for any type
that implements <code>Display</code>. If we tried to use <code>to_string</code> without adding a
colon and specifying the <code>Display</code> trait after the trait name, wed get an
error saying that no method named <code>to_string</code> was found for the type <code>&amp;Self</code> in
the current scope.</p>
<p>Lets see what happens when we try to implement <code>OutlinePrint</code> on a type that
doesnt implement <code>Display</code>, such as the <code>Point</code> struct:</p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre><code class="language-rust ignore does_not_compile"><span class="boring">use std::fmt;
</span><span class="boring">
</span><span class="boring">trait OutlinePrint: fmt::Display {
</span><span class="boring"> fn outline_print(&amp;self) {
</span><span class="boring"> let output = self.to_string();
</span><span class="boring"> let len = output.len();
</span><span class="boring"> println!("{}", "*".repeat(len + 4));
</span><span class="boring"> println!("*{}*", " ".repeat(len + 2));
</span><span class="boring"> println!("* {output} *");
</span><span class="boring"> println!("*{}*", " ".repeat(len + 2));
</span><span class="boring"> println!("{}", "*".repeat(len + 4));
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span>struct Point {
x: i32,
y: i32,
}
impl OutlinePrint for Point {}
<span class="boring">
</span><span class="boring">fn main() {
</span><span class="boring"> let p = Point { x: 1, y: 3 };
</span><span class="boring"> p.outline_print();
</span><span class="boring">}</span></code></pre>
</figure>
<p>We get an error saying that <code>Display</code> is required but not implemented:</p>
<pre><code class="language-console">$ cargo run
Compiling traits-example v0.1.0 (file:///projects/traits-example)
error[E0277]: `Point` doesn't implement `std::fmt::Display`
--&gt; src/main.rs:20:23
|
20 | impl OutlinePrint for Point {}
| ^^^^^ the trait `std::fmt::Display` is not implemented for `Point`
|
note: required by a bound in `OutlinePrint`
--&gt; src/main.rs:3:21
|
3 | trait OutlinePrint: fmt::Display {
| ^^^^^^^^^^^^ required by this bound in `OutlinePrint`
error[E0277]: `Point` doesn't implement `std::fmt::Display`
--&gt; src/main.rs:24:7
|
24 | p.outline_print();
| ^^^^^^^^^^^^^ the trait `std::fmt::Display` is not implemented for `Point`
|
note: required by a bound in `OutlinePrint::outline_print`
--&gt; src/main.rs:3:21
|
3 | trait OutlinePrint: fmt::Display {
| ^^^^^^^^^^^^ required by this bound in `OutlinePrint::outline_print`
4 | fn outline_print(&amp;self) {
| ------------- required by a bound in this associated function
For more information about this error, try `rustc --explain E0277`.
error: could not compile `traits-example` (bin "traits-example") due to 2 previous errors
</code></pre>
<p>To fix this, we implement <code>Display</code> on <code>Point</code> and satisfy the constraint that
<code>OutlinePrint</code> requires, like so:</p>
<figure class="listing">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024"><span class="boring">trait OutlinePrint: fmt::Display {
</span><span class="boring"> fn outline_print(&amp;self) {
</span><span class="boring"> let output = self.to_string();
</span><span class="boring"> let len = output.len();
</span><span class="boring"> println!("{}", "*".repeat(len + 4));
</span><span class="boring"> println!("*{}*", " ".repeat(len + 2));
</span><span class="boring"> println!("* {output} *");
</span><span class="boring"> println!("*{}*", " ".repeat(len + 2));
</span><span class="boring"> println!("{}", "*".repeat(len + 4));
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">struct Point {
</span><span class="boring"> x: i32,
</span><span class="boring"> y: i32,
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">impl OutlinePrint for Point {}
</span><span class="boring">
</span>use std::fmt;
impl fmt::Display for Point {
fn fmt(&amp;self, f: &amp;mut fmt::Formatter) -&gt; fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
<span class="boring">
</span><span class="boring">fn main() {
</span><span class="boring"> let p = Point { x: 1, y: 3 };
</span><span class="boring"> p.outline_print();
</span><span class="boring">}</span></code></pre>
</figure>
<p>Then, implementing the <code>OutlinePrint</code> trait on <code>Point</code> will compile
successfully, and we can call <code>outline_print</code> on a <code>Point</code> instance to display
it within an outline of asterisks.</p>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="using-the-newtype-pattern-to-implement-external-traits-on-external-types"></a>
<a id="using-the-newtype-pattern-to-implement-external-traits"></a></p>
<h3 id="implementing-external-traits-with-the-newtype-pattern"><a class="header" href="#implementing-external-traits-with-the-newtype-pattern">Implementing External Traits with the Newtype Pattern</a></h3>
<p>In the <a href="../ch10/ch10-02-traits.html#implementing-a-trait-on-a-type">“Implementing a Trait on a Type”</a><!--
ignore --> section in Chapter 10, we mentioned the orphan rule that states
were only allowed to implement a trait on a type if either the trait or the
type, or both, are local to our crate. Its possible to get around this
restriction using the newtype pattern, which involves creating a new type in a
tuple struct. (We covered tuple structs in the <a href="../ch05/ch05-01-defining-structs.html#creating-different-types-with-tuple-structs">“Creating Different Types with
Tuple Structs”</a><!-- ignore --> section in Chapter 5.) The tuple
struct will have one field and be a thin wrapper around the type for which we
want to implement a trait. Then, the wrapper type is local to our crate, and we
can implement the trait on the wrapper. <em>Newtype</em> is a term that originates
from the Haskell programming language. There is no runtime performance penalty
for using this pattern, and the wrapper type is elided at compile time.</p>
<p>As an example, lets say we want to implement <code>Display</code> on <code>Vec&lt;T&gt;</code>, which the
orphan rule prevents us from doing directly because the <code>Display</code> trait and the
<code>Vec&lt;T&gt;</code> type are defined outside our crate. We can make a <code>Wrapper</code> struct
that holds an instance of <code>Vec&lt;T&gt;</code>; then, we can implement <code>Display</code> on
<code>Wrapper</code> and use the <code>Vec&lt;T&gt;</code> value, as shown in Listing 20-24.</p>
<figure class="listing" id="listing-20-24">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024">use std::fmt;
struct Wrapper(Vec&lt;String&gt;);
impl fmt::Display for Wrapper {
fn fmt(&amp;self, f: &amp;mut fmt::Formatter) -&gt; fmt::Result {
write!(f, "[{}]", self.0.join(", "))
}
}
fn main() {
let w = Wrapper(vec![String::from("hello"), String::from("world")]);
println!("w = {w}");
}</code></pre>
<figcaption><a href="#listing-20-24">Listing 20-24</a>: Creating a <code>Wrapper</code> type around <code>Vec&lt;String&gt;</code> to implement <code>Display</code></figcaption>
</figure>
<p>The implementation of <code>Display</code> uses <code>self.0</code> to access the inner <code>Vec&lt;T&gt;</code>
because <code>Wrapper</code> is a tuple struct and <code>Vec&lt;T&gt;</code> is the item at index 0 in the
tuple. Then, we can use the functionality of the <code>Display</code> trait on <code>Wrapper</code>.</p>
<p>The downside of using this technique is that <code>Wrapper</code> is a new type, so it
doesnt have the methods of the value its holding. We would have to implement
all the methods of <code>Vec&lt;T&gt;</code> directly on <code>Wrapper</code> such that the methods
delegate to <code>self.0</code>, which would allow us to treat <code>Wrapper</code> exactly like a
<code>Vec&lt;T&gt;</code>. If we wanted the new type to have every method the inner type has,
implementing the <code>Deref</code> trait on the <code>Wrapper</code> to return the inner type would
be a solution (we discussed implementing the <code>Deref</code> trait in the <a href="../ch15/ch15-02-deref.html#treating-smart-pointers-like-regular-references">“Treating
Smart Pointers Like Regular References”</a><!-- ignore -->
section in Chapter 15). If we didnt want the <code>Wrapper</code> type to have all the
methods of the inner type—for example, to restrict the <code>Wrapper</code> types
behavior—we would have to implement just the methods we do want manually.</p>
<p>This newtype pattern is also useful even when traits are not involved. Lets
switch focus and look at some advanced ways to interact with Rusts type system.</p>
</body>
</html>

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Redirecting...</title>
</head>
<body>
<p>Redirecting to... <a href="../ch21/ch21-02-multithreaded.html">ch21-02-multithreaded.html</a>.</p>
</body>
</html>

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Redirecting...</title>
</head>
<body>
<p>Redirecting to... <a href="ch20-02-advanced-traits.html">ch20-02-advanced-traits.html</a>.</p>
</body>
</html>

View File

@@ -0,0 +1,352 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Advanced Types</title>
</head>
<body>
<h2 id="advanced-types"><a class="header" href="#advanced-types">Advanced Types</a></h2>
<p>The Rust type system has some features that weve so far mentioned but havent
yet discussed. Well start by discussing newtypes in general as we examine why
they are useful as types. Then, well move on to type aliases, a feature
similar to newtypes but with slightly different semantics. Well also discuss
the <code>!</code> type and dynamically sized types.</p>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="using-the-newtype-pattern-for-type-safety-and-abstraction"></a></p>
<h3 id="type-safety-and-abstraction-with-the-newtype-pattern"><a class="header" href="#type-safety-and-abstraction-with-the-newtype-pattern">Type Safety and Abstraction with the Newtype Pattern</a></h3>
<p>This section assumes youve read the earlier section <a href="ch20-02-advanced-traits.html#implementing-external-traits-with-the-newtype-pattern">“Implementing External
Traits with the Newtype Pattern”</a><!-- ignore -->. The newtype pattern
is also useful for tasks beyond those weve discussed so far, including
statically enforcing that values are never confused and indicating the units of
a value. You saw an example of using newtypes to indicate units in Listing
20-16: Recall that the <code>Millimeters</code> and <code>Meters</code> structs wrapped <code>u32</code> values
in a newtype. If we wrote a function with a parameter of type <code>Millimeters</code>, we
wouldnt be able to compile a program that accidentally tried to call that
function with a value of type <code>Meters</code> or a plain <code>u32</code>.</p>
<p>We can also use the newtype pattern to abstract away some implementation
details of a type: The new type can expose a public API that is different from
the API of the private inner type.</p>
<p>Newtypes can also hide internal implementation. For example, we could provide a
<code>People</code> type to wrap a <code>HashMap&lt;i32, String&gt;</code> that stores a persons ID
associated with their name. Code using <code>People</code> would only interact with the
public API we provide, such as a method to add a name string to the <code>People</code>
collection; that code wouldnt need to know that we assign an <code>i32</code> ID to names
internally. The newtype pattern is a lightweight way to achieve encapsulation
to hide implementation details, which we discussed in the <a href="../ch18/ch18-01-what-is-oo.html#encapsulation-that-hides-implementation-details">“Encapsulation that
Hides Implementation
Details”</a><!-- ignore -->
section in Chapter 18.</p>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="creating-type-synonyms-with-type-aliases"></a></p>
<h3 id="type-synonyms-and-type-aliases"><a class="header" href="#type-synonyms-and-type-aliases">Type Synonyms and Type Aliases</a></h3>
<p>Rust provides the ability to declare a <em>type alias</em> to give an existing type
another name. For this we use the <code>type</code> keyword. For example, we can create
the alias <code>Kilometers</code> to <code>i32</code> like so:</p>
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
</span> type Kilometers = i32;
<span class="boring">
</span><span class="boring"> let x: i32 = 5;
</span><span class="boring"> let y: Kilometers = 5;
</span><span class="boring">
</span><span class="boring"> println!("x + y = {}", x + y);
</span><span class="boring">}</span></code></pre>
<p>Now the alias <code>Kilometers</code> is a <em>synonym</em> for <code>i32</code>; unlike the <code>Millimeters</code>
and <code>Meters</code> types we created in Listing 20-16, <code>Kilometers</code> is not a separate,
new type. Values that have the type <code>Kilometers</code> will be treated the same as
values of type <code>i32</code>:</p>
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
</span> type Kilometers = i32;
let x: i32 = 5;
let y: Kilometers = 5;
println!("x + y = {}", x + y);
<span class="boring">}</span></code></pre>
<p>Because <code>Kilometers</code> and <code>i32</code> are the same type, we can add values of both
types and can pass <code>Kilometers</code> values to functions that take <code>i32</code>
parameters. However, using this method, we dont get the type-checking benefits
that we get from the newtype pattern discussed earlier. In other words, if we
mix up <code>Kilometers</code> and <code>i32</code> values somewhere, the compiler will not give us
an error.</p>
<p>The main use case for type synonyms is to reduce repetition. For example, we
might have a lengthy type like this:</p>
<pre><code class="language-rust ignore">Box&lt;dyn Fn() + Send + 'static&gt;</code></pre>
<p>Writing this lengthy type in function signatures and as type annotations all
over the code can be tiresome and error-prone. Imagine having a project full of
code like that in Listing 20-25.</p>
<figure class="listing" id="listing-20-25">
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
</span> let f: Box&lt;dyn Fn() + Send + 'static&gt; = Box::new(|| println!("hi"));
fn takes_long_type(f: Box&lt;dyn Fn() + Send + 'static&gt;) {
// --snip--
}
fn returns_long_type() -&gt; Box&lt;dyn Fn() + Send + 'static&gt; {
// --snip--
<span class="boring"> Box::new(|| ())
</span> }
<span class="boring">}</span></code></pre>
<figcaption><a href="#listing-20-25">Listing 20-25</a>: Using a long type in many places</figcaption>
</figure>
<p>A type alias makes this code more manageable by reducing the repetition. In
Listing 20-26, weve introduced an alias named <code>Thunk</code> for the verbose type and
can replace all uses of the type with the shorter alias <code>Thunk</code>.</p>
<figure class="listing" id="listing-20-26">
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
</span> type Thunk = Box&lt;dyn Fn() + Send + 'static&gt;;
let f: Thunk = Box::new(|| println!("hi"));
fn takes_long_type(f: Thunk) {
// --snip--
}
fn returns_long_type() -&gt; Thunk {
// --snip--
<span class="boring"> Box::new(|| ())
</span> }
<span class="boring">}</span></code></pre>
<figcaption><a href="#listing-20-26">Listing 20-26</a>: Introducing a type alias, <code>Thunk</code>, to reduce repetition</figcaption>
</figure>
<p>This code is much easier to read and write! Choosing a meaningful name for a
type alias can help communicate your intent as well (<em>thunk</em> is a word for code
to be evaluated at a later time, so its an appropriate name for a closure that
gets stored).</p>
<p>Type aliases are also commonly used with the <code>Result&lt;T, E&gt;</code> type for reducing
repetition. Consider the <code>std::io</code> module in the standard library. I/O
operations often return a <code>Result&lt;T, E&gt;</code> to handle situations when operations
fail to work. This library has a <code>std::io::Error</code> struct that represents all
possible I/O errors. Many of the functions in <code>std::io</code> will be returning
<code>Result&lt;T, E&gt;</code> where the <code>E</code> is <code>std::io::Error</code>, such as these functions in
the <code>Write</code> trait:</p>
<pre><code class="language-rust noplayground">use std::fmt;
use std::io::Error;
pub trait Write {
fn write(&amp;mut self, buf: &amp;[u8]) -&gt; Result&lt;usize, Error&gt;;
fn flush(&amp;mut self) -&gt; Result&lt;(), Error&gt;;
fn write_all(&amp;mut self, buf: &amp;[u8]) -&gt; Result&lt;(), Error&gt;;
fn write_fmt(&amp;mut self, fmt: fmt::Arguments) -&gt; Result&lt;(), Error&gt;;
}</code></pre>
<p>The <code>Result&lt;..., Error&gt;</code> is repeated a lot. As such, <code>std::io</code> has this type
alias declaration:</p>
<pre><code class="language-rust noplayground"><span class="boring">use std::fmt;
</span><span class="boring">
</span>type Result&lt;T&gt; = std::result::Result&lt;T, std::io::Error&gt;;
<span class="boring">
</span><span class="boring">pub trait Write {
</span><span class="boring"> fn write(&amp;mut self, buf: &amp;[u8]) -&gt; Result&lt;usize&gt;;
</span><span class="boring"> fn flush(&amp;mut self) -&gt; Result&lt;()&gt;;
</span><span class="boring">
</span><span class="boring"> fn write_all(&amp;mut self, buf: &amp;[u8]) -&gt; Result&lt;()&gt;;
</span><span class="boring"> fn write_fmt(&amp;mut self, fmt: fmt::Arguments) -&gt; Result&lt;()&gt;;
</span><span class="boring">}</span></code></pre>
<p>Because this declaration is in the <code>std::io</code> module, we can use the fully
qualified alias <code>std::io::Result&lt;T&gt;</code>; that is, a <code>Result&lt;T, E&gt;</code> with the <code>E</code>
filled in as <code>std::io::Error</code>. The <code>Write</code> trait function signatures end up
looking like this:</p>
<pre><code class="language-rust noplayground"><span class="boring">use std::fmt;
</span><span class="boring">
</span><span class="boring">type Result&lt;T&gt; = std::result::Result&lt;T, std::io::Error&gt;;
</span><span class="boring">
</span>pub trait Write {
fn write(&amp;mut self, buf: &amp;[u8]) -&gt; Result&lt;usize&gt;;
fn flush(&amp;mut self) -&gt; Result&lt;()&gt;;
fn write_all(&amp;mut self, buf: &amp;[u8]) -&gt; Result&lt;()&gt;;
fn write_fmt(&amp;mut self, fmt: fmt::Arguments) -&gt; Result&lt;()&gt;;
}</code></pre>
<p>The type alias helps in two ways: It makes code easier to write <em>and</em> it gives
us a consistent interface across all of <code>std::io</code>. Because its an alias, its
just another <code>Result&lt;T, E&gt;</code>, which means we can use any methods that work on
<code>Result&lt;T, E&gt;</code> with it, as well as special syntax like the <code>?</code> operator.</p>
<h3 id="the-never-type-that-never-returns"><a class="header" href="#the-never-type-that-never-returns">The Never Type That Never Returns</a></h3>
<p>Rust has a special type named <code>!</code> thats known in type theory lingo as the
<em>empty type</em> because it has no values. We prefer to call it the <em>never type</em>
because it stands in the place of the return type when a function will never
return. Here is an example:</p>
<pre><code class="language-rust noplayground">fn bar() -&gt; ! {
// --snip--
<span class="boring"> panic!();
</span>}</code></pre>
<p>This code is read as “the function <code>bar</code> returns never.” Functions that return
never are called <em>diverging functions</em>. We cant create values of the type <code>!</code>,
so <code>bar</code> can never possibly return.</p>
<p>But what use is a type you can never create values for? Recall the code from
Listing 2-5, part of the number-guessing game; weve reproduced a bit of it
here in Listing 20-27.</p>
<figure class="listing" id="listing-20-27">
<pre><code class="language-rust ignore"><span class="boring">use std::cmp::Ordering;
</span><span class="boring">use std::io;
</span><span class="boring">
</span><span class="boring">use rand::Rng;
</span><span class="boring">
</span><span class="boring">fn main() {
</span><span class="boring"> println!("Guess the number!");
</span><span class="boring">
</span><span class="boring"> let secret_number = rand::thread_rng().gen_range(1..=100);
</span><span class="boring">
</span><span class="boring"> println!("The secret number is: {secret_number}");
</span><span class="boring">
</span><span class="boring"> loop {
</span><span class="boring"> println!("Please input your guess.");
</span><span class="boring">
</span><span class="boring"> let mut guess = String::new();
</span><span class="boring">
</span><span class="boring"> // --snip--
</span><span class="boring">
</span><span class="boring"> io::stdin()
</span><span class="boring"> .read_line(&amp;mut guess)
</span><span class="boring"> .expect("Failed to read line");
</span><span class="boring">
</span> let guess: u32 = match guess.trim().parse() {
Ok(num) =&gt; num,
Err(_) =&gt; continue,
};
<span class="boring">
</span><span class="boring"> println!("You guessed: {guess}");
</span><span class="boring">
</span><span class="boring"> // --snip--
</span><span class="boring">
</span><span class="boring"> match guess.cmp(&amp;secret_number) {
</span><span class="boring"> Ordering::Less =&gt; println!("Too small!"),
</span><span class="boring"> Ordering::Greater =&gt; println!("Too big!"),
</span><span class="boring"> Ordering::Equal =&gt; {
</span><span class="boring"> println!("You win!");
</span><span class="boring"> break;
</span><span class="boring"> }
</span><span class="boring"> }
</span><span class="boring"> }
</span><span class="boring">}</span></code></pre>
<figcaption><a href="#listing-20-27">Listing 20-27</a>: A <code>match</code> with an arm that ends in <code>continue</code></figcaption>
</figure>
<p>At the time, we skipped over some details in this code. In <a href="../ch06/ch06-02-match.html#the-match-control-flow-construct">“The <code>match</code>
Control Flow Construct”</a><!-- ignore -->
section in Chapter 6, we discussed that <code>match</code> arms must all return the same
type. So, for example, the following code doesnt work:</p>
<pre><code class="language-rust ignore does_not_compile"><span class="boring">fn main() {
</span><span class="boring"> let guess = "3";
</span> let guess = match guess.trim().parse() {
Ok(_) =&gt; 5,
Err(_) =&gt; "hello",
};
<span class="boring">}</span></code></pre>
<p>The type of <code>guess</code> in this code would have to be an integer <em>and</em> a string,
and Rust requires that <code>guess</code> have only one type. So, what does <code>continue</code>
return? How were we allowed to return a <code>u32</code> from one arm and have another arm
that ends with <code>continue</code> in Listing 20-27?</p>
<p>As you might have guessed, <code>continue</code> has a <code>!</code> value. That is, when Rust
computes the type of <code>guess</code>, it looks at both match arms, the former with a
value of <code>u32</code> and the latter with a <code>!</code> value. Because <code>!</code> can never have a
value, Rust decides that the type of <code>guess</code> is <code>u32</code>.</p>
<p>The formal way of describing this behavior is that expressions of type <code>!</code> can
be coerced into any other type. Were allowed to end this <code>match</code> arm with
<code>continue</code> because <code>continue</code> doesnt return a value; instead, it moves control
back to the top of the loop, so in the <code>Err</code> case, we never assign a value to
<code>guess</code>.</p>
<p>The never type is useful with the <code>panic!</code> macro as well. Recall the <code>unwrap</code>
function that we call on <code>Option&lt;T&gt;</code> values to produce a value or panic with
this definition:</p>
<pre><code class="language-rust ignore"><span class="boring">enum Option&lt;T&gt; {
</span><span class="boring"> Some(T),
</span><span class="boring"> None,
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">use crate::Option::*;
</span><span class="boring">
</span>impl&lt;T&gt; Option&lt;T&gt; {
pub fn unwrap(self) -&gt; T {
match self {
Some(val) =&gt; val,
None =&gt; panic!("called `Option::unwrap()` on a `None` value"),
}
}
}</code></pre>
<p>In this code, the same thing happens as in the <code>match</code> in Listing 20-27: Rust
sees that <code>val</code> has the type <code>T</code> and <code>panic!</code> has the type <code>!</code>, so the result
of the overall <code>match</code> expression is <code>T</code>. This code works because <code>panic!</code>
doesnt produce a value; it ends the program. In the <code>None</code> case, we wont be
returning a value from <code>unwrap</code>, so this code is valid.</p>
<p>One final expression that has the type <code>!</code> is a loop:</p>
<pre><code class="language-rust ignore"><span class="boring">fn main() {
</span> print!("forever ");
loop {
print!("and ever ");
}
<span class="boring">}</span></code></pre>
<p>Here, the loop never ends, so <code>!</code> is the value of the expression. However, this
wouldnt be true if we included a <code>break</code>, because the loop would terminate
when it got to the <code>break</code>.</p>
<h3 id="dynamically-sized-types-and-the-sized-trait"><a class="header" href="#dynamically-sized-types-and-the-sized-trait">Dynamically Sized Types and the <code>Sized</code> Trait</a></h3>
<p>Rust needs to know certain details about its types, such as how much space to
allocate for a value of a particular type. This leaves one corner of its type
system a little confusing at first: the concept of <em>dynamically sized types</em>.
Sometimes referred to as <em>DSTs</em> or <em>unsized types</em>, these types let us write
code using values whose size we can know only at runtime.</p>
<p>Lets dig into the details of a dynamically sized type called <code>str</code>, which
weve been using throughout the book. Thats right, not <code>&amp;str</code>, but <code>str</code> on
its own, is a DST. In many cases, such as when storing text entered by a user,
we cant know how long the string is until runtime. That means we cant create
a variable of type <code>str</code>, nor can we take an argument of type <code>str</code>. Consider
the following code, which does not work:</p>
<pre><code class="language-rust ignore does_not_compile"><span class="boring">fn main() {
</span> let s1: str = "Hello there!";
let s2: str = "How's it going?";
<span class="boring">}</span></code></pre>
<p>Rust needs to know how much memory to allocate for any value of a particular
type, and all values of a type must use the same amount of memory. If Rust
allowed us to write this code, these two <code>str</code> values would need to take up the
same amount of space. But they have different lengths: <code>s1</code> needs 12 bytes of
storage and <code>s2</code> needs 15. This is why its not possible to create a variable
holding a dynamically sized type.</p>
<p>So, what do we do? In this case, you already know the answer: We make the type
of <code>s1</code> and <code>s2</code> string slice (<code>&amp;str</code>) rather than <code>str</code>. Recall from the
<a href="../ch04/ch04-03-slices.html#string-slices">“String Slices”</a><!-- ignore --> section in Chapter 4 that the
slice data structure only stores the starting position and the length of the
slice. So, although <code>&amp;T</code> is a single value that stores the memory address of
where the <code>T</code> is located, a string slice is <em>two</em> values: the address of the
<code>str</code> and its length. As such, we can know the size of a string slice value at
compile time: Its twice the length of a <code>usize</code>. That is, we always know the
size of a string slice, no matter how long the string it refers to is. In
general, this is the way in which dynamically sized types are used in Rust:
They have an extra bit of metadata that stores the size of the dynamic
information. The golden rule of dynamically sized types is that we must always
put values of dynamically sized types behind a pointer of some kind.</p>
<p>We can combine <code>str</code> with all kinds of pointers: for example, <code>Box&lt;str&gt;</code> or
<code>Rc&lt;str&gt;</code>. In fact, youve seen this before but with a different dynamically
sized type: traits. Every trait is a dynamically sized type we can refer to by
using the name of the trait. In the <a href="../ch18/ch18-02-trait-objects.html#using-trait-objects-to-abstract-over-shared-behavior">“Using Trait Objects to Abstract over
Shared Behavior”</a><!--
ignore --> section in Chapter 18, we mentioned that to use traits as trait
objects, we must put them behind a pointer, such as <code>&amp;dyn Trait</code> or <code>Box&lt;dyn Trait&gt;</code> (<code>Rc&lt;dyn Trait&gt;</code> would work too).</p>
<p>To work with DSTs, Rust provides the <code>Sized</code> trait to determine whether or not
a types size is known at compile time. This trait is automatically implemented
for everything whose size is known at compile time. In addition, Rust
implicitly adds a bound on <code>Sized</code> to every generic function. That is, a
generic function definition like this:</p>
<pre><code class="language-rust ignore">fn generic&lt;T&gt;(t: T) {
// --snip--
}</code></pre>
<p>is actually treated as though we had written this:</p>
<pre><code class="language-rust ignore">fn generic&lt;T: Sized&gt;(t: T) {
// --snip--
}</code></pre>
<p>By default, generic functions will work only on types that have a known size at
compile time. However, you can use the following special syntax to relax this
restriction:</p>
<pre><code class="language-rust ignore">fn generic&lt;T: ?Sized&gt;(t: &amp;T) {
// --snip--
}</code></pre>
<p>A trait bound on <code>?Sized</code> means “<code>T</code> may or may not be <code>Sized</code>,” and this
notation overrides the default that generic types must have a known size at
compile time. The <code>?Trait</code> syntax with this meaning is only available for
<code>Sized</code>, not any other traits.</p>
<p>Also note that we switched the type of the <code>t</code> parameter from <code>T</code> to <code>&amp;T</code>.
Because the type might not be <code>Sized</code>, we need to use it behind some kind of
pointer. In this case, weve chosen a reference.</p>
<p>Next, well talk about functions and closures!</p>
</body>
</html>

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Redirecting...</title>
</head>
<body>
<p>Redirecting to... <a href="../ch21/ch21-03-graceful-shutdown-and-cleanup.html">ch21-03-graceful-shutdown-and-cleanup.html</a>.</p>
</body>
</html>

View File

@@ -0,0 +1,210 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Advanced Functions and Closures</title>
</head>
<body>
<h2 id="advanced-functions-and-closures"><a class="header" href="#advanced-functions-and-closures">Advanced Functions and Closures</a></h2>
<p>This section explores some advanced features related to functions and closures,
including function pointers and returning closures.</p>
<h3 id="function-pointers"><a class="header" href="#function-pointers">Function Pointers</a></h3>
<p>Weve talked about how to pass closures to functions; you can also pass regular
functions to functions! This technique is useful when you want to pass a
function youve already defined rather than defining a new closure. Functions
coerce to the type <code>fn</code> (with a lowercase <em>f</em>), not to be confused with the
<code>Fn</code> closure trait. The <code>fn</code> type is called a <em>function pointer</em>. Passing
functions with function pointers will allow you to use functions as arguments
to other functions.</p>
<p>The syntax for specifying that a parameter is a function pointer is similar to
that of closures, as shown in Listing 20-28, where weve defined a function
<code>add_one</code> that adds 1 to its parameter. The function <code>do_twice</code> takes two
parameters: a function pointer to any function that takes an <code>i32</code> parameter
and returns an <code>i32</code>, and one <code>i32</code> value. The <code>do_twice</code> function calls the
function <code>f</code> twice, passing it the <code>arg</code> value, then adds the two function call
results together. The <code>main</code> function calls <code>do_twice</code> with the arguments
<code>add_one</code> and <code>5</code>.</p>
<figure class="listing" id="listing-20-28">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024">fn add_one(x: i32) -&gt; i32 {
x + 1
}
fn do_twice(f: fn(i32) -&gt; i32, arg: i32) -&gt; i32 {
f(arg) + f(arg)
}
fn main() {
let answer = do_twice(add_one, 5);
println!("The answer is: {answer}");
}</code></pre>
<figcaption><a href="#listing-20-28">Listing 20-28</a>: Using the <code>fn</code> type to accept a function pointer as an argument</figcaption>
</figure>
<p>This code prints <code>The answer is: 12</code>. We specify that the parameter <code>f</code> in
<code>do_twice</code> is an <code>fn</code> that takes one parameter of type <code>i32</code> and returns an
<code>i32</code>. We can then call <code>f</code> in the body of <code>do_twice</code>. In <code>main</code>, we can pass
the function name <code>add_one</code> as the first argument to <code>do_twice</code>.</p>
<p>Unlike closures, <code>fn</code> is a type rather than a trait, so we specify <code>fn</code> as the
parameter type directly rather than declaring a generic type parameter with one
of the <code>Fn</code> traits as a trait bound.</p>
<p>Function pointers implement all three of the closure traits (<code>Fn</code>, <code>FnMut</code>, and
<code>FnOnce</code>), meaning you can always pass a function pointer as an argument for a
function that expects a closure. Its best to write functions using a generic
type and one of the closure traits so that your functions can accept either
functions or closures.</p>
<p>That said, one example of where you would want to only accept <code>fn</code> and not
closures is when interfacing with external code that doesnt have closures: C
functions can accept functions as arguments, but C doesnt have closures.</p>
<p>As an example of where you could use either a closure defined inline or a named
function, lets look at a use of the <code>map</code> method provided by the <code>Iterator</code>
trait in the standard library. To use the <code>map</code> method to turn a vector of
numbers into a vector of strings, we could use a closure, as in Listing 20-29.</p>
<figure class="listing" id="listing-20-29">
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
</span> let list_of_numbers = vec![1, 2, 3];
let list_of_strings: Vec&lt;String&gt; =
list_of_numbers.iter().map(|i| i.to_string()).collect();
<span class="boring">}</span></code></pre>
<figcaption><a href="#listing-20-29">Listing 20-29</a>: Using a closure with the <code>map</code> method to convert numbers to strings</figcaption>
</figure>
<p>Or we could name a function as the argument to <code>map</code> instead of the closure.
Listing 20-30 shows what this would look like.</p>
<figure class="listing" id="listing-20-30">
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
</span> let list_of_numbers = vec![1, 2, 3];
let list_of_strings: Vec&lt;String&gt; =
list_of_numbers.iter().map(ToString::to_string).collect();
<span class="boring">}</span></code></pre>
<figcaption><a href="#listing-20-30">Listing 20-30</a>: Using the <code>String::to_string</code> function with the <code>map</code> method to convert numbers to strings</figcaption>
</figure>
<p>Note that we must use the fully qualified syntax that we talked about in the
<a href="ch20-02-advanced-traits.html#advanced-traits">“Advanced Traits”</a><!-- ignore --> section because there are
multiple functions available named <code>to_string</code>.</p>
<p>Here, were using the <code>to_string</code> function defined in the <code>ToString</code> trait,
which the standard library has implemented for any type that implements
<code>Display</code>.</p>
<p>Recall from the <a href="../ch06/ch06-01-defining-an-enum.html#enum-values">“Enum Values”</a><!-- ignore --> section in Chapter
6 that the name of each enum variant that we define also becomes an initializer
function. We can use these initializer functions as function pointers that
implement the closure traits, which means we can specify the initializer
functions as arguments for methods that take closures, as seen in Listing 20-31.</p>
<figure class="listing" id="listing-20-31">
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
</span> enum Status {
Value(u32),
Stop,
}
let list_of_statuses: Vec&lt;Status&gt; = (0u32..20).map(Status::Value).collect();
<span class="boring">}</span></code></pre>
<figcaption><a href="#listing-20-31">Listing 20-31</a>: Using an enum initializer with the <code>map</code> method to create a <code>Status</code> instance from numbers</figcaption>
</figure>
<p>Here, we create <code>Status::Value</code> instances using each <code>u32</code> value in the range
that <code>map</code> is called on by using the initializer function of <code>Status::Value</code>.
Some people prefer this style and some people prefer to use closures. They
compile to the same code, so use whichever style is clearer to you.</p>
<h3 id="returning-closures"><a class="header" href="#returning-closures">Returning Closures</a></h3>
<p>Closures are represented by traits, which means you cant return closures
directly. In most cases where you might want to return a trait, you can instead
use the concrete type that implements the trait as the return value of the
function. However, you cant usually do that with closures because they dont
have a concrete type that is returnable; youre not allowed to use the function
pointer <code>fn</code> as a return type if the closure captures any values from its
scope, for example.</p>
<p>Instead, you will normally use the <code>impl Trait</code> syntax we learned about in
Chapter 10. You can return any function type, using <code>Fn</code>, <code>FnOnce</code>, and <code>FnMut</code>.
For example, the code in Listing 20-32 will compile just fine.</p>
<figure class="listing" id="listing-20-32">
<pre class="playground"><code class="language-rust edition2024"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>fn returns_closure() -&gt; impl Fn(i32) -&gt; i32 {
|x| x + 1
}
<span class="boring">}</span></code></pre>
<figcaption><a href="#listing-20-32">Listing 20-32</a>: Returning a closure from a function using the <code>impl Trait</code> syntax</figcaption>
</figure>
<p>However, as we noted in the <a href="../ch13/ch13-01-closures.html#closure-type-inference-and-annotation">“Inferring and Annotating Closure
Types”</a><!-- ignore --> section in Chapter 13, each closure is
also its own distinct type. If you need to work with multiple functions that
have the same signature but different implementations, you will need to use a
trait object for them. Consider what happens if you write code like that shown
in Listing 20-33.</p>
<figure class="listing" id="listing-20-33">
<span class="file-name">Filename: src/main.rs</span>
<pre><code class="language-rust ignore does_not_compile">fn main() {
let handlers = vec![returns_closure(), returns_initialized_closure(123)];
for handler in handlers {
let output = handler(5);
println!("{output}");
}
}
fn returns_closure() -&gt; impl Fn(i32) -&gt; i32 {
|x| x + 1
}
fn returns_initialized_closure(init: i32) -&gt; impl Fn(i32) -&gt; i32 {
move |x| x + init
}</code></pre>
<figcaption><a href="#listing-20-33">Listing 20-33</a>: Creating a <code>Vec&lt;T&gt;</code> of closures defined by functions that return <code>impl Fn</code> types</figcaption>
</figure>
<p>Here we have two functions, <code>returns_closure</code> and <code>returns_initialized_closure</code>,
which both return <code>impl Fn(i32) -&gt; i32</code>. Notice that the closures that they
return are different, even though they implement the same type. If we try to
compile this, Rust lets us know that it wont work:</p>
<pre><code class="language-text">$ cargo build
Compiling functions-example v0.1.0 (file:///projects/functions-example)
error[E0308]: mismatched types
--&gt; src/main.rs:2:44
|
2 | let handlers = vec![returns_closure(), returns_initialized_closure(123)];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found a different opaque type
...
9 | fn returns_closure() -&gt; impl Fn(i32) -&gt; i32 {
| ------------------- the expected opaque type
...
13 | fn returns_initialized_closure(init: i32) -&gt; impl Fn(i32) -&gt; i32 {
| ------------------- the found opaque type
|
= note: expected opaque type `impl Fn(i32) -&gt; i32`
found opaque type `impl Fn(i32) -&gt; i32`
= note: distinct uses of `impl Trait` result in different opaque types
For more information about this error, try `rustc --explain E0308`.
error: could not compile `functions-example` (bin "functions-example") due to 1 previous error
</code></pre>
<p>The error message tells us that whenever we return an <code>impl Trait</code>, Rust
creates a unique <em>opaque type</em>, a type where we cannot see into the details of
what Rust constructs for us, nor can we guess the type Rust will generate to
write ourselves. So, even though these functions return closures that implement
the same trait, <code>Fn(i32) -&gt; i32</code>, the opaque types Rust generates for each are
distinct. (This is similar to how Rust produces different concrete types for
distinct async blocks even when they have the same output type, as we saw in
<a href="../ch17/ch17-03-more-futures.html">“The <code>Pin</code> Type and the <code>Unpin</code> Trait”</a><!-- ignore --> in
Chapter 17.) We have seen a solution to this problem a few times now: We can
use a trait object, as in Listing 20-34.</p>
<figure class="listing" id="listing-20-34">
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
</span><span class="boring"> let handlers = vec![returns_closure(), returns_initialized_closure(123)];
</span><span class="boring"> for handler in handlers {
</span><span class="boring"> let output = handler(5);
</span><span class="boring"> println!("{output}");
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span>fn returns_closure() -&gt; Box&lt;dyn Fn(i32) -&gt; i32&gt; {
Box::new(|x| x + 1)
}
fn returns_initialized_closure(init: i32) -&gt; Box&lt;dyn Fn(i32) -&gt; i32&gt; {
Box::new(move |x| x + init)
}</code></pre>
<figcaption><a href="#listing-20-34">Listing 20-34</a>: Creating a <code>Vec&lt;T&gt;</code> of closures defined by functions that return <code>Box&lt;dyn Fn&gt;</code> so that they have the same type</figcaption>
</figure>
<p>This code will compile just fine. For more about trait objects, refer to the
section <a href="../ch18/ch18-02-trait-objects.html">“Using Trait Objects To Abstract over Shared
Behavior”</a><!-- ignore --> in Chapter 18.</p>
<p>Next, lets look at macros!</p>
</body>
</html>

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Redirecting...</title>
</head>
<body>
<p>Redirecting to... <a href="ch20-03-advanced-types.html">ch20-03-advanced-types.html</a>.</p>
</body>
</html>

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Redirecting...</title>
</head>
<body>
<p>Redirecting to... <a href="ch20-04-advanced-functions-and-closures.html">ch20-04-advanced-functions-and-closures.html</a>.</p>
</body>
</html>

485
ch20/ch20-05-macros.html Normal file
View File

@@ -0,0 +1,485 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Macros</title>
</head>
<body>
<h2 id="macros"><a class="header" href="#macros">Macros</a></h2>
<p>Weve used macros like <code>println!</code> throughout this book, but we havent fully
explored what a macro is and how it works. The term <em>macro</em> refers to a family
of features in Rust—declarative macros with <code>macro_rules!</code> and three kinds of
procedural macros:</p>
<ul>
<li>Custom <code>#[derive]</code> macros that specify code added with the <code>derive</code> attribute
used on structs and enums</li>
<li>Attribute-like macros that define custom attributes usable on any item</li>
<li>Function-like macros that look like function calls but operate on the tokens
specified as their argument</li>
</ul>
<p>Well talk about each of these in turn, but first, lets look at why we even
need macros when we already have functions.</p>
<h3 id="the-difference-between-macros-and-functions"><a class="header" href="#the-difference-between-macros-and-functions">The Difference Between Macros and Functions</a></h3>
<p>Fundamentally, macros are a way of writing code that writes other code, which
is known as <em>metaprogramming</em>. In Appendix C, we discuss the <code>derive</code>
attribute, which generates an implementation of various traits for you. Weve
also used the <code>println!</code> and <code>vec!</code> macros throughout the book. All of these
macros <em>expand</em> to produce more code than the code youve written manually.</p>
<p>Metaprogramming is useful for reducing the amount of code you have to write and
maintain, which is also one of the roles of functions. However, macros have
some additional powers that functions dont have.</p>
<p>A function signature must declare the number and type of parameters the
function has. Macros, on the other hand, can take a variable number of
parameters: We can call <code>println!("hello")</code> with one argument or
<code>println!("hello {}", name)</code> with two arguments. Also, macros are expanded
before the compiler interprets the meaning of the code, so a macro can, for
example, implement a trait on a given type. A function cant, because it gets
called at runtime and a trait needs to be implemented at compile time.</p>
<p>The downside to implementing a macro instead of a function is that macro
definitions are more complex than function definitions because youre writing
Rust code that writes Rust code. Due to this indirection, macro definitions are
generally more difficult to read, understand, and maintain than function
definitions.</p>
<p>Another important difference between macros and functions is that you must
define macros or bring them into scope <em>before</em> you call them in a file, as
opposed to functions you can define anywhere and call anywhere.</p>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="declarative-macros-with-macro_rules-for-general-metaprogramming"></a></p>
<h3 id="declarative-macros-for-general-metaprogramming"><a class="header" href="#declarative-macros-for-general-metaprogramming">Declarative Macros for General Metaprogramming</a></h3>
<p>The most widely used form of macros in Rust is the <em>declarative macro</em>. These
are also sometimes referred to as “macros by example,” “<code>macro_rules!</code> macros,”
or just plain “macros.” At their core, declarative macros allow you to write
something similar to a Rust <code>match</code> expression. As discussed in Chapter 6,
<code>match</code> expressions are control structures that take an expression, compare the
resultant value of the expression to patterns, and then run the code associated
with the matching pattern. Macros also compare a value to patterns that are
associated with particular code: In this situation, the value is the literal
Rust source code passed to the macro; the patterns are compared with the
structure of that source code; and the code associated with each pattern, when
matched, replaces the code passed to the macro. This all happens during
compilation.</p>
<p>To define a macro, you use the <code>macro_rules!</code> construct. Lets explore how to
use <code>macro_rules!</code> by looking at how the <code>vec!</code> macro is defined. Chapter 8
covered how we can use the <code>vec!</code> macro to create a new vector with particular
values. For example, the following macro creates a new vector containing three
integers:</p>
<pre class="playground"><code class="language-rust edition2024"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>let v: Vec&lt;u32&gt; = vec![1, 2, 3];
<span class="boring">}</span></code></pre>
<p>We could also use the <code>vec!</code> macro to make a vector of two integers or a vector
of five string slices. We wouldnt be able to use a function to do the same
because we wouldnt know the number or type of values up front.</p>
<p>Listing 20-35 shows a slightly simplified definition of the <code>vec!</code> macro.</p>
<figure class="listing" id="listing-20-35">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground">#[macro_export]
macro_rules! vec {
( $( $x:expr ),* ) =&gt; {
{
let mut temp_vec = Vec::new();
$(
temp_vec.push($x);
)*
temp_vec
}
};
}</code></pre>
<figcaption><a href="#listing-20-35">Listing 20-35</a>: A simplified version of the <code>vec!</code> macro definition</figcaption>
</figure>
<section class="note" aria-role="note">
<p>Note: The actual definition of the <code>vec!</code> macro in the standard library
includes code to pre-allocate the correct amount of memory up front. That code
is an optimization that we dont include here, to make the example simpler.</p>
</section>
<p>The <code>#[macro_export]</code> annotation indicates that this macro should be made
available whenever the crate in which the macro is defined is brought into
scope. Without this annotation, the macro cant be brought into scope.</p>
<p>We then start the macro definition with <code>macro_rules!</code> and the name of the
macro were defining <em>without</em> the exclamation mark. The name, in this case
<code>vec</code>, is followed by curly brackets denoting the body of the macro definition.</p>
<p>The structure in the <code>vec!</code> body is similar to the structure of a <code>match</code>
expression. Here we have one arm with the pattern <code>( $( $x:expr ),* )</code>,
followed by <code>=&gt;</code> and the block of code associated with this pattern. If the
pattern matches, the associated block of code will be emitted. Given that this
is the only pattern in this macro, there is only one valid way to match; any
other pattern will result in an error. More complex macros will have more than
one arm.</p>
<p>Valid pattern syntax in macro definitions is different from the pattern syntax
covered in Chapter 19 because macro patterns are matched against Rust code
structure rather than values. Lets walk through what the pattern pieces in
Listing 20-29 mean; for the full macro pattern syntax, see the <a href="../reference/macros-by-example.html">Rust
Reference</a>.</p>
<p>First, we use a set of parentheses to encompass the whole pattern. We use a
dollar sign (<code>$</code>) to declare a variable in the macro system that will contain
the Rust code matching the pattern. The dollar sign makes it clear this is a
macro variable as opposed to a regular Rust variable. Next comes a set of
parentheses that captures values that match the pattern within the parentheses
for use in the replacement code. Within <code>$()</code> is <code>$x:expr</code>, which matches any
Rust expression and gives the expression the name <code>$x</code>.</p>
<p>The comma following <code>$()</code> indicates that a literal comma separator character
must appear between each instance of the code that matches the code in <code>$()</code>.
The <code>*</code> specifies that the pattern matches zero or more of whatever precedes
the <code>*</code>.</p>
<p>When we call this macro with <code>vec![1, 2, 3];</code>, the <code>$x</code> pattern matches three
times with the three expressions <code>1</code>, <code>2</code>, and <code>3</code>.</p>
<p>Now lets look at the pattern in the body of the code associated with this arm:
<code>temp_vec.push()</code> within <code>$()*</code> is generated for each part that matches <code>$()</code>
in the pattern zero or more times depending on how many times the pattern
matches. The <code>$x</code> is replaced with each expression matched. When we call this
macro with <code>vec![1, 2, 3];</code>, the code generated that replaces this macro call
will be the following:</p>
<pre><code class="language-rust ignore">{
let mut temp_vec = Vec::new();
temp_vec.push(1);
temp_vec.push(2);
temp_vec.push(3);
temp_vec
}</code></pre>
<p>Weve defined a macro that can take any number of arguments of any type and can
generate code to create a vector containing the specified elements.</p>
<p>To learn more about how to write macros, consult the online documentation or
other resources, such as <a href="https://veykril.github.io/tlborm/">“The Little Book of Rust Macros”</a> started by
Daniel Keep and continued by Lukas Wirth.</p>
<h3 id="procedural-macros-for-generating-code-from-attributes"><a class="header" href="#procedural-macros-for-generating-code-from-attributes">Procedural Macros for Generating Code from Attributes</a></h3>
<p>The second form of macros is the procedural macro, which acts more like a
function (and is a type of procedure). <em>Procedural macros</em> accept some code as
an input, operate on that code, and produce some code as an output rather than
matching against patterns and replacing the code with other code as declarative
macros do. The three kinds of procedural macros are custom <code>derive</code>,
attribute-like, and function-like, and all work in a similar fashion.</p>
<p>When creating procedural macros, the definitions must reside in their own crate
with a special crate type. This is for complex technical reasons that we hope
to eliminate in the future. In Listing 20-36, we show how to define a
procedural macro, where <code>some_attribute</code> is a placeholder for using a specific
macro variety.</p>
<figure class="listing" id="listing-20-36">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust ignore">use proc_macro::TokenStream;
#[some_attribute]
pub fn some_name(input: TokenStream) -&gt; TokenStream {
}</code></pre>
<figcaption><a href="#listing-20-36">Listing 20-36</a>: An example of defining a procedural macro</figcaption>
</figure>
<p>The function that defines a procedural macro takes a <code>TokenStream</code> as an input
and produces a <code>TokenStream</code> as an output. The <code>TokenStream</code> type is defined by
the <code>proc_macro</code> crate that is included with Rust and represents a sequence of
tokens. This is the core of the macro: The source code that the macro is
operating on makes up the input <code>TokenStream</code>, and the code the macro produces
is the output <code>TokenStream</code>. The function also has an attribute attached to it
that specifies which kind of procedural macro were creating. We can have
multiple kinds of procedural macros in the same crate.</p>
<p>Lets look at the different kinds of procedural macros. Well start with a
custom <code>derive</code> macro and then explain the small dissimilarities that make the
other forms different.</p>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="how-to-write-a-custom-derive-macro"></a></p>
<h3 id="custom-derive-macros"><a class="header" href="#custom-derive-macros">Custom <code>derive</code> Macros</a></h3>
<p>Lets create a crate named <code>hello_macro</code> that defines a trait named
<code>HelloMacro</code> with one associated function named <code>hello_macro</code>. Rather than
making our users implement the <code>HelloMacro</code> trait for each of their types,
well provide a procedural macro so that users can annotate their type with
<code>#[derive(HelloMacro)]</code> to get a default implementation of the <code>hello_macro</code>
function. The default implementation will print <code>Hello, Macro! My name is TypeName!</code> where <code>TypeName</code> is the name of the type on which this trait has
been defined. In other words, well write a crate that enables another
programmer to write code like Listing 20-37 using our crate.</p>
<figure class="listing" id="listing-20-37">
<span class="file-name">Filename: src/main.rs</span>
<pre><code class="language-rust ignore does_not_compile">use hello_macro::HelloMacro;
use hello_macro_derive::HelloMacro;
#[derive(HelloMacro)]
struct Pancakes;
fn main() {
Pancakes::hello_macro();
}</code></pre>
<figcaption><a href="#listing-20-37">Listing 20-37</a>: The code a user of our crate will be able to write when using our procedural macro</figcaption>
</figure>
<p>This code will print <code>Hello, Macro! My name is Pancakes!</code> when were done. The
first step is to make a new library crate, like this:</p>
<pre><code class="language-console">$ cargo new hello_macro --lib
</code></pre>
<p>Next, in Listing 20-38, well define the <code>HelloMacro</code> trait and its associated
function.</p>
<figure class="listing" id="listing-20-38">
<span class="file-name">Filename: src/lib.rs</span>
<pre><code class="language-rust noplayground">pub trait HelloMacro {
fn hello_macro();
}</code></pre>
<figcaption><a href="#listing-20-38">Listing 20-38</a>: A simple trait that we will use with the <code>derive</code> macro</figcaption>
</figure>
<p>We have a trait and its function. At this point, our crate user could implement
the trait to achieve the desired functionality, as in Listing 20-39.</p>
<figure class="listing" id="listing-20-39">
<span class="file-name">Filename: src/main.rs</span>
<pre><code class="language-rust ignore">use hello_macro::HelloMacro;
struct Pancakes;
impl HelloMacro for Pancakes {
fn hello_macro() {
println!("Hello, Macro! My name is Pancakes!");
}
}
fn main() {
Pancakes::hello_macro();
}</code></pre>
<figcaption><a href="#listing-20-39">Listing 20-39</a>: How it would look if users wrote a manual implementation of the <code>HelloMacro</code> trait</figcaption>
</figure>
<p>However, they would need to write the implementation block for each type they
wanted to use with <code>hello_macro</code>; we want to spare them from having to do this
work.</p>
<p>Additionally, we cant yet provide the <code>hello_macro</code> function with default
implementation that will print the name of the type the trait is implemented
on: Rust doesnt have reflection capabilities, so it cant look up the types
name at runtime. We need a macro to generate code at compile time.</p>
<p>The next step is to define the procedural macro. At the time of this writing,
procedural macros need to be in their own crate. Eventually, this restriction
might be lifted. The convention for structuring crates and macro crates is as
follows: For a crate named <code>foo</code>, a custom <code>derive</code> procedural macro crate is
called <code>foo_derive</code>. Lets start a new crate called <code>hello_macro_derive</code> inside
our <code>hello_macro</code> project:</p>
<pre><code class="language-console">$ cargo new hello_macro_derive --lib
</code></pre>
<p>Our two crates are tightly related, so we create the procedural macro crate
within the directory of our <code>hello_macro</code> crate. If we change the trait
definition in <code>hello_macro</code>, well have to change the implementation of the
procedural macro in <code>hello_macro_derive</code> as well. The two crates will need to
be published separately, and programmers using these crates will need to add
both as dependencies and bring them both into scope. We could instead have the
<code>hello_macro</code> crate use <code>hello_macro_derive</code> as a dependency and re-export the
procedural macro code. However, the way weve structured the project makes it
possible for programmers to use <code>hello_macro</code> even if they dont want the
<code>derive</code> functionality.</p>
<p>We need to declare the <code>hello_macro_derive</code> crate as a procedural macro crate.
Well also need functionality from the <code>syn</code> and <code>quote</code> crates, as youll see
in a moment, so we need to add them as dependencies. Add the following to the
<em>Cargo.toml</em> file for <code>hello_macro_derive</code>:</p>
<figure class="listing">
<span class="file-name">Filename: hello_macro_derive/Cargo.toml</span>
<pre><code class="language-toml">[lib]
proc-macro = true
[dependencies]
syn = "2.0"
quote = "1.0"
</code></pre>
</figure>
<p>To start defining the procedural macro, place the code in Listing 20-40 into
your <em>src/lib.rs</em> file for the <code>hello_macro_derive</code> crate. Note that this code
wont compile until we add a definition for the <code>impl_hello_macro</code> function.</p>
<figure class="listing" id="listing-20-40">
<span class="file-name">Filename: hello_macro_derive/src/lib.rs</span>
<pre><code class="language-rust ignore does_not_compile">use proc_macro::TokenStream;
use quote::quote;
#[proc_macro_derive(HelloMacro)]
pub fn hello_macro_derive(input: TokenStream) -&gt; TokenStream {
// Construct a representation of Rust code as a syntax tree
// that we can manipulate.
let ast = syn::parse(input).unwrap();
// Build the trait implementation.
impl_hello_macro(&amp;ast)
}</code></pre>
<figcaption><a href="#listing-20-40">Listing 20-40</a>: Code that most procedural macro crates will require in order to process Rust code</figcaption>
</figure>
<p>Notice that weve split the code into the <code>hello_macro_derive</code> function, which
is responsible for parsing the <code>TokenStream</code>, and the <code>impl_hello_macro</code>
function, which is responsible for transforming the syntax tree: This makes
writing a procedural macro more convenient. The code in the outer function
(<code>hello_macro_derive</code> in this case) will be the same for almost every
procedural macro crate you see or create. The code you specify in the body of
the inner function (<code>impl_hello_macro</code> in this case) will be different
depending on your procedural macros purpose.</p>
<p>Weve introduced three new crates: <code>proc_macro</code>, <a href="https://crates.io/crates/syn"><code>syn</code></a><!-- ignore -->,
and <a href="https://crates.io/crates/quote"><code>quote</code></a><!-- ignore -->. The <code>proc_macro</code> crate comes with Rust,
so we didnt need to add that to the dependencies in <em>Cargo.toml</em>. The
<code>proc_macro</code> crate is the compilers API that allows us to read and manipulate
Rust code from our code.</p>
<p>The <code>syn</code> crate parses Rust code from a string into a data structure that we
can perform operations on. The <code>quote</code> crate turns <code>syn</code> data structures back
into Rust code. These crates make it much simpler to parse any sort of Rust
code we might want to handle: Writing a full parser for Rust code is no simple
task.</p>
<p>The <code>hello_macro_derive</code> function will be called when a user of our library
specifies <code>#[derive(HelloMacro)]</code> on a type. This is possible because weve
annotated the <code>hello_macro_derive</code> function here with <code>proc_macro_derive</code> and
specified the name <code>HelloMacro</code>, which matches our trait name; this is the
convention most procedural macros follow.</p>
<p>The <code>hello_macro_derive</code> function first converts the <code>input</code> from a
<code>TokenStream</code> to a data structure that we can then interpret and perform
operations on. This is where <code>syn</code> comes into play. The <code>parse</code> function in
<code>syn</code> takes a <code>TokenStream</code> and returns a <code>DeriveInput</code> struct representing the
parsed Rust code. Listing 20-41 shows the relevant parts of the <code>DeriveInput</code>
struct we get from parsing the <code>struct Pancakes;</code> string.</p>
<figure class="listing" id="listing-20-41">
<pre><code class="language-rust ignore">DeriveInput {
// --snip--
ident: Ident {
ident: "Pancakes",
span: #0 bytes(95..103)
},
data: Struct(
DataStruct {
struct_token: Struct,
fields: Unit,
semi_token: Some(
Semi
)
}
)
}</code></pre>
<figcaption><a href="#listing-20-41">Listing 20-41</a>: The <code>DeriveInput</code> instance we get when parsing the code that has the macros attribute in Listing 20-37</figcaption>
</figure>
<p>The fields of this struct show that the Rust code weve parsed is a unit struct
with the <code>ident</code> (<em>identifier</em>, meaning the name) of <code>Pancakes</code>. There are more
fields on this struct for describing all sorts of Rust code; check the <a href="https://docs.rs/syn/2.0/syn/struct.DeriveInput.html"><code>syn</code>
documentation for <code>DeriveInput</code></a> for more information.</p>
<p>Soon well define the <code>impl_hello_macro</code> function, which is where well build
the new Rust code we want to include. But before we do, note that the output
for our <code>derive</code> macro is also a <code>TokenStream</code>. The returned <code>TokenStream</code> is
added to the code that our crate users write, so when they compile their crate,
theyll get the extra functionality that we provide in the modified
<code>TokenStream</code>.</p>
<p>You might have noticed that were calling <code>unwrap</code> to cause the
<code>hello_macro_derive</code> function to panic if the call to the <code>syn::parse</code> function
fails here. Its necessary for our procedural macro to panic on errors because
<code>proc_macro_derive</code> functions must return <code>TokenStream</code> rather than <code>Result</code> to
conform to the procedural macro API. Weve simplified this example by using
<code>unwrap</code>; in production code, you should provide more specific error messages
about what went wrong by using <code>panic!</code> or <code>expect</code>.</p>
<p>Now that we have the code to turn the annotated Rust code from a <code>TokenStream</code>
into a <code>DeriveInput</code> instance, lets generate the code that implements the
<code>HelloMacro</code> trait on the annotated type, as shown in Listing 20-42.</p>
<figure class="listing" id="listing-20-42">
<span class="file-name">Filename: hello_macro_derive/src/lib.rs</span>
<pre><code class="language-rust ignore"><span class="boring">use proc_macro::TokenStream;
</span><span class="boring">use quote::quote;
</span><span class="boring">
</span><span class="boring">#[proc_macro_derive(HelloMacro)]
</span><span class="boring">pub fn hello_macro_derive(input: TokenStream) -&gt; TokenStream {
</span><span class="boring"> // Construct a representation of Rust code as a syntax tree
</span><span class="boring"> // that we can manipulate
</span><span class="boring"> let ast = syn::parse(input).unwrap();
</span><span class="boring">
</span><span class="boring"> // Build the trait implementation
</span><span class="boring"> impl_hello_macro(&amp;ast)
</span><span class="boring">}
</span><span class="boring">
</span>fn impl_hello_macro(ast: &amp;syn::DeriveInput) -&gt; TokenStream {
let name = &amp;ast.ident;
let generated = quote! {
impl HelloMacro for #name {
fn hello_macro() {
println!("Hello, Macro! My name is {}!", stringify!(#name));
}
}
};
generated.into()
}</code></pre>
<figcaption><a href="#listing-20-42">Listing 20-42</a>: Implementing the <code>HelloMacro</code> trait using the parsed Rust code</figcaption>
</figure>
<p>We get an <code>Ident</code> struct instance containing the name (identifier) of the
annotated type using <code>ast.ident</code>. The struct in Listing 20-41 shows that when
we run the <code>impl_hello_macro</code> function on the code in Listing 20-37, the
<code>ident</code> we get will have the <code>ident</code> field with a value of <code>"Pancakes"</code>. Thus,
the <code>name</code> variable in Listing 20-42 will contain an <code>Ident</code> struct instance
that, when printed, will be the string <code>"Pancakes"</code>, the name of the struct in
Listing 20-37.</p>
<p>The <code>quote!</code> macro lets us define the Rust code that we want to return. The
compiler expects something different from the direct result of the <code>quote!</code>
macros execution, so we need to convert it to a <code>TokenStream</code>. We do this by
calling the <code>into</code> method, which consumes this intermediate representation and
returns a value of the required <code>TokenStream</code> type.</p>
<p>The <code>quote!</code> macro also provides some very cool templating mechanics: We can
enter <code>#name</code>, and <code>quote!</code> will replace it with the value in the variable
<code>name</code>. You can even do some repetition similar to the way regular macros work.
Check out <a href="https://docs.rs/quote">the <code>quote</code> crates docs</a> for a thorough introduction.</p>
<p>We want our procedural macro to generate an implementation of our <code>HelloMacro</code>
trait for the type the user annotated, which we can get by using <code>#name</code>. The
trait implementation has the one function <code>hello_macro</code>, whose body contains the
functionality we want to provide: printing <code>Hello, Macro! My name is</code> and then
the name of the annotated type.</p>
<p>The <code>stringify!</code> macro used here is built into Rust. It takes a Rust
expression, such as <code>1 + 2</code>, and at compile time turns the expression into a
string literal, such as <code>"1 + 2"</code>. This is different from <code>format!</code> or
<code>println!</code>, which are macros that evaluate the expression and then turn the
result into a <code>String</code>. There is a possibility that the <code>#name</code> input might be
an expression to print literally, so we use <code>stringify!</code>. Using <code>stringify!</code>
also saves an allocation by converting <code>#name</code> to a string literal at compile
time.</p>
<p>At this point, <code>cargo build</code> should complete successfully in both <code>hello_macro</code>
and <code>hello_macro_derive</code>. Lets hook up these crates to the code in Listing
20-37 to see the procedural macro in action! Create a new binary project in
your <em>projects</em> directory using <code>cargo new pancakes</code>. We need to add
<code>hello_macro</code> and <code>hello_macro_derive</code> as dependencies in the <code>pancakes</code>
crates <em>Cargo.toml</em>. If youre publishing your versions of <code>hello_macro</code> and
<code>hello_macro_derive</code> to <a href="https://crates.io/">crates.io</a><!-- ignore -->, they
would be regular dependencies; if not, you can specify them as <code>path</code>
dependencies as follows:</p>
<pre><code class="language-toml">[dependencies]
hello_macro = { path = "../hello_macro" }
hello_macro_derive = { path = "../hello_macro/hello_macro_derive" }
</code></pre>
<p>Put the code in Listing 20-37 into <em>src/main.rs</em>, and run <code>cargo run</code>: It
should print <code>Hello, Macro! My name is Pancakes!</code>. The implementation of the
<code>HelloMacro</code> trait from the procedural macro was included without the
<code>pancakes</code> crate needing to implement it; the <code>#[derive(HelloMacro)]</code> added the
trait implementation.</p>
<p>Next, lets explore how the other kinds of procedural macros differ from custom
<code>derive</code> macros.</p>
<h3 id="attribute-like-macros"><a class="header" href="#attribute-like-macros">Attribute-Like Macros</a></h3>
<p>Attribute-like macros are similar to custom <code>derive</code> macros, but instead of
generating code for the <code>derive</code> attribute, they allow you to create new
attributes. Theyre also more flexible: <code>derive</code> only works for structs and
enums; attributes can be applied to other items as well, such as functions.
Heres an example of using an attribute-like macro. Say you have an attribute
named <code>route</code> that annotates functions when using a web application framework:</p>
<pre><code class="language-rust ignore">#[route(GET, "/")]
fn index() {</code></pre>
<p>This <code>#[route]</code> attribute would be defined by the framework as a procedural
macro. The signature of the macro definition function would look like this:</p>
<pre><code class="language-rust ignore">#[proc_macro_attribute]
pub fn route(attr: TokenStream, item: TokenStream) -&gt; TokenStream {</code></pre>
<p>Here, we have two parameters of type <code>TokenStream</code>. The first is for the
contents of the attribute: the <code>GET, "/"</code> part. The second is the body of the
item the attribute is attached to: in this case, <code>fn index() {}</code> and the rest
of the functions body.</p>
<p>Other than that, attribute-like macros work the same way as custom <code>derive</code>
macros: You create a crate with the <code>proc-macro</code> crate type and implement a
function that generates the code you want!</p>
<h3 id="function-like-macros"><a class="header" href="#function-like-macros">Function-Like Macros</a></h3>
<p>Function-like macros define macros that look like function calls. Similarly to
<code>macro_rules!</code> macros, theyre more flexible than functions; for example, they
can take an unknown number of arguments. However, <code>macro_rules!</code> macros can
only be defined using the match-like syntax we discussed in the <a href="#declarative-macros-with-macro_rules-for-general-metaprogramming">“Declarative
Macros for General Metaprogramming”</a><!-- ignore --> section earlier.
Function-like macros take a <code>TokenStream</code> parameter, and their definition
manipulates that <code>TokenStream</code> using Rust code as the other two types of
procedural macros do. An example of a function-like macro is an <code>sql!</code> macro
that might be called like so:</p>
<pre><code class="language-rust ignore">let sql = sql!(SELECT * FROM posts WHERE id=1);</code></pre>
<p>This macro would parse the SQL statement inside it and check that its
syntactically correct, which is much more complex processing than a
<code>macro_rules!</code> macro can do. The <code>sql!</code> macro would be defined like this:</p>
<pre><code class="language-rust ignore">#[proc_macro]
pub fn sql(input: TokenStream) -&gt; TokenStream {</code></pre>
<p>This definition is similar to the custom <code>derive</code> macros signature: We receive
the tokens that are inside the parentheses and return the code we wanted to
generate.</p>
<h2 id="summary"><a class="header" href="#summary">Summary</a></h2>
<p>Whew! Now you have some Rust features in your toolbox that you likely wont use
often, but youll know theyre available in very particular circumstances.
Weve introduced several complex topics so that when you encounter them in
error message suggestions or in other peoples code, youll be able to
recognize these concepts and syntax. Use this chapter as a reference to guide
you to solutions.</p>
<p>Next, well put everything weve discussed throughout the book into practice
and do one more project!</p>
</body>
</html>

12
ch20/ch20-06-macros.html Normal file
View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Redirecting...</title>
</head>
<body>
<p>Redirecting to... <a href="ch20-05-macros.html">ch20-05-macros.html</a>.</p>
</body>
</html>