RustBook/ch15-02-deref.html

542 lines
44 KiB
HTML
Raw Normal View History

2020-01-06 20:57:15 +00:00
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Treating Smart Pointers Like Regular References with the Deref Trait - The Rust Programming Language</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link href="googleFonts/css.css" rel="stylesheet" type="text/css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
<link rel="stylesheet" href="ferris.css">
<link rel="stylesheet" href="theme/2018-edition.css">
</head>
<body>
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "light" : "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
var html = document.querySelector('html');
html.classList.remove('no-js')
html.classList.remove('light')
html.classList.add(theme);
html.classList.add('js');
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div id="sidebar-scrollbox" class="sidebar-scrollbox">
<ol class="chapter"><li class="expanded affix "><a href="title-page.html">The Rust Programming Language</a></li><li class="expanded affix "><a href="foreword.html">Foreword</a></li><li class="expanded affix "><a href="ch00-00-introduction.html">Introduction</a></li><li class="expanded "><a href="ch01-00-getting-started.html"><strong aria-hidden="true">1.</strong> Getting Started</a></li><li><ol class="section"><li class="expanded "><a href="ch01-01-installation.html"><strong aria-hidden="true">1.1.</strong> Installation</a></li><li class="expanded "><a href="ch01-02-hello-world.html"><strong aria-hidden="true">1.2.</strong> Hello, World!</a></li><li class="expanded "><a href="ch01-03-hello-cargo.html"><strong aria-hidden="true">1.3.</strong> Hello, Cargo!</a></li></ol></li><li class="expanded "><a href="ch02-00-guessing-game-tutorial.html"><strong aria-hidden="true">2.</strong> Programming a Guessing Game</a></li><li class="expanded "><a href="ch03-00-common-programming-concepts.html"><strong aria-hidden="true">3.</strong> Common Programming Concepts</a></li><li><ol class="section"><li class="expanded "><a href="ch03-01-variables-and-mutability.html"><strong aria-hidden="true">3.1.</strong> Variables and Mutability</a></li><li class="expanded "><a href="ch03-02-data-types.html"><strong aria-hidden="true">3.2.</strong> Data Types</a></li><li class="expanded "><a href="ch03-03-how-functions-work.html"><strong aria-hidden="true">3.3.</strong> Functions</a></li><li class="expanded "><a href="ch03-04-comments.html"><strong aria-hidden="true">3.4.</strong> Comments</a></li><li class="expanded "><a href="ch03-05-control-flow.html"><strong aria-hidden="true">3.5.</strong> Control Flow</a></li></ol></li><li class="expanded "><a href="ch04-00-understanding-ownership.html"><strong aria-hidden="true">4.</strong> Understanding Ownership</a></li><li><ol class="section"><li class="expanded "><a href="ch04-01-what-is-ownership.html"><strong aria-hidden="true">4.1.</strong> What is Ownership?</a></li><li class="expanded "><a href="ch04-02-references-and-borrowing.html"><strong aria-hidden="true">4.2.</strong> References and Borrowing</a></li><li class="expanded "><a href="ch04-03-slices.html"><strong aria-hidden="true">4.3.</strong> The Slice Type</a></li></ol></li><li class="expanded "><a href="ch05-00-structs.html"><strong aria-hidden="true">5.</strong> Using Structs to Structure Related Data</a></li><li><ol class="section"><li class="expanded "><a href="ch05-01-defining-structs.html"><strong aria-hidden="true">5.1.</strong> Defining and Instantiating Structs</a></li><li class="expanded "><a href="ch05-02-example-structs.html"><strong aria-hidden="true">5.2.</strong> An Example Program Using Structs</a></li><li class="expanded "><a href="ch05-03-method-syntax.html"><strong aria-hidden="true">5.3.</strong> Method Syntax</a></li></ol></li><li class="expanded "><a href="ch06-00-enums.html"><strong aria-hidden="true">6.</strong> Enums and Pattern Matching</a></li><li><ol class="section"><li class="expanded "><a href="ch06-01-defining-an-enum.html"><strong aria-hidden="true">6.1.</strong> Defining an Enum</a></li><li class="expanded "><a href="ch06-02-match.html"><strong aria-hidden="true">6.2.</strong> The match Control Flow Operator</a></li><li class="expanded "><a href="ch06-03-if-let.html"><strong aria-hidden="true">6.3.</strong> Concise Control Flow with if let</a></li></ol></li><li class="expanded "><a href="ch07-00-managing-growing-projects-with-packages-crates-and-modules.html"><strong aria-hidden="true">7.</strong> Managing Growing Projects with Packages, Crates, and Modules</a></li><li><ol class="section"><li class="expanded "><a href="ch07-01-packages-and-crates.html"><strong aria-hidden="true">7.1.</strong> Packages and Crates</a></li><li class="expanded "><a href="ch07-02-defining-modules-to-control-scope-and-privacy.html"><strong aria-hidden="true">7.2.</strong> Defining Modules to Control Scope and Privacy</a></li><li class="expanded "><a href="ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html"><
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar" class="menu-bar">
<div id="menu-bar-sticky-container">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">The Rust Programming Language</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h2><a class="header" href="#treating-smart-pointers-like-regular-references-with-the-deref-trait" id="treating-smart-pointers-like-regular-references-with-the-deref-trait">Treating Smart Pointers Like Regular References with the <code>Deref</code> Trait</a></h2>
<p>Implementing the <code>Deref</code> trait allows you to customize the behavior of the
<em>dereference operator</em>, <code>*</code> (as opposed to the multiplication or glob
operator). By implementing <code>Deref</code> in such a way that a smart pointer can be
treated like a regular reference, you can write code that operates on
references and use that code with smart pointers too.</p>
<p>Lets first look at how the dereference operator works with regular references.
Then well try to define a custom type that behaves like <code>Box&lt;T&gt;</code>, and see why
the dereference operator doesnt work like a reference on our newly defined
type. Well explore how implementing the <code>Deref</code> trait makes it possible for
smart pointers to work in ways similar to references. Then well look at
Rusts <em>deref coercion</em> feature and how it lets us work with either references
or smart pointers.</p>
<blockquote>
<p>Note: theres one big difference between the <code>MyBox&lt;T&gt;</code> type were about to
build and the real <code>Box&lt;T&gt;</code>: our version will not store its data on the heap.
We are focusing this example on <code>Deref</code>, so where the data is actually stored
is less important than the pointer-like behavior.</p>
</blockquote>
<h3><a class="header" href="#following-the-pointer-to-the-value-with-the-dereference-operator" id="following-the-pointer-to-the-value-with-the-dereference-operator">Following the Pointer to the Value with the Dereference Operator</a></h3>
<p>A regular reference is a type of pointer, and one way to think of a pointer is
as an arrow to a value stored somewhere else. In Listing 15-6, we create a
reference to an <code>i32</code> value and then use the dereference operator to follow the
reference to the data:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><pre class="playpen"><code class="language-rust">fn main() {
let x = 5;
let y = &amp;x;
assert_eq!(5, x);
assert_eq!(5, *y);
}
</code></pre></pre>
<p><span class="caption">Listing 15-6: Using the dereference operator to follow a
reference to an <code>i32</code> value</span></p>
<p>The variable <code>x</code> holds an <code>i32</code> value, <code>5</code>. We set <code>y</code> equal to a reference to
<code>x</code>. We can assert that <code>x</code> is equal to <code>5</code>. However, if we want to make an
assertion about the value in <code>y</code>, we have to use <code>*y</code> to follow the reference
to the value its pointing to (hence <em>dereference</em>). Once we dereference <code>y</code>,
we have access to the integer value <code>y</code> is pointing to that we can compare with
<code>5</code>.</p>
<p>If we tried to write <code>assert_eq!(5, y);</code> instead, we would get this compilation
error:</p>
<pre><code class="language-text">error[E0277]: can't compare `{integer}` with `&amp;{integer}`
--&gt; src/main.rs:6:5
|
6 | assert_eq!(5, y);
| ^^^^^^^^^^^^^^^^^ no implementation for `{integer} == &amp;{integer}`
|
= help: the trait `std::cmp::PartialEq&lt;&amp;{integer}&gt;` is not implemented for
`{integer}`
</code></pre>
<p>Comparing a number and a reference to a number isnt allowed because theyre
different types. We must use the dereference operator to follow the reference
to the value its pointing to.</p>
<h3><a class="header" href="#using-boxt-like-a-reference" id="using-boxt-like-a-reference">Using <code>Box&lt;T&gt;</code> Like a Reference</a></h3>
<p>We can rewrite the code in Listing 15-6 to use a <code>Box&lt;T&gt;</code> instead of a
reference; the dereference operator will work as shown in Listing 15-7:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><pre class="playpen"><code class="language-rust">fn main() {
let x = 5;
let y = Box::new(x);
assert_eq!(5, x);
assert_eq!(5, *y);
}
</code></pre></pre>
<p><span class="caption">Listing 15-7: Using the dereference operator on a
<code>Box&lt;i32&gt;</code></span></p>
<p>The only difference between Listing 15-7 and Listing 15-6 is that here we set
<code>y</code> to be an instance of a box pointing to the value in <code>x</code> rather than a
reference pointing to the value of <code>x</code>. In the last assertion, we can use the
dereference operator to follow the boxs pointer in the same way that we did
when <code>y</code> was a reference. Next, well explore what is special about <code>Box&lt;T&gt;</code>
that enables us to use the dereference operator by defining our own box type.</p>
<h3><a class="header" href="#defining-our-own-smart-pointer" id="defining-our-own-smart-pointer">Defining Our Own Smart Pointer</a></h3>
<p>Lets build a smart pointer similar to the <code>Box&lt;T&gt;</code> type provided by the
standard library to experience how smart pointers behave differently from
references by default. Then well look at how to add the ability to use the
dereference operator.</p>
<p>The <code>Box&lt;T&gt;</code> type is ultimately defined as a tuple struct with one element, so
Listing 15-8 defines a <code>MyBox&lt;T&gt;</code> type in the same way. Well also define a
<code>new</code> function to match the <code>new</code> function defined on <code>Box&lt;T&gt;</code>.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><pre class="playpen"><code class="language-rust">
<span class="boring">#![allow(unused_variables)]
</span><span class="boring">fn main() {
</span>struct MyBox&lt;T&gt;(T);
impl&lt;T&gt; MyBox&lt;T&gt; {
fn new(x: T) -&gt; MyBox&lt;T&gt; {
MyBox(x)
}
}
<span class="boring">}
</span></code></pre></pre>
<p><span class="caption">Listing 15-8: Defining a <code>MyBox&lt;T&gt;</code> type</span></p>
<p>We define a struct named <code>MyBox</code> and declare a generic parameter <code>T</code>, because
we want our type to hold values of any type. The <code>MyBox</code> type is a tuple struct
with one element of type <code>T</code>. The <code>MyBox::new</code> function takes one parameter of
type <code>T</code> and returns a <code>MyBox</code> instance that holds the value passed in.</p>
<p>Lets try adding the <code>main</code> function in Listing 15-7 to Listing 15-8 and
changing it to use the <code>MyBox&lt;T&gt;</code> type weve defined instead of <code>Box&lt;T&gt;</code>. The
code in Listing 15-9 wont compile because Rust doesnt know how to dereference
<code>MyBox</code>.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><code class="language-rust ignore does_not_compile">fn main() {
let x = 5;
let y = MyBox::new(x);
assert_eq!(5, x);
assert_eq!(5, *y);
}
</code></pre>
<p><span class="caption">Listing 15-9: Attempting to use <code>MyBox&lt;T&gt;</code> in the same
way we used references and <code>Box&lt;T&gt;</code></span></p>
<p>Heres the resulting compilation error:</p>
<pre><code class="language-text">error[E0614]: type `MyBox&lt;{integer}&gt;` cannot be dereferenced
--&gt; src/main.rs:14:19
|
14 | assert_eq!(5, *y);
| ^^
</code></pre>
<p>Our <code>MyBox&lt;T&gt;</code> type cant be dereferenced because we havent implemented that
ability on our type. To enable dereferencing with the <code>*</code> operator, we
implement the <code>Deref</code> trait.</p>
<h3><a class="header" href="#treating-a-type-like-a-reference-by-implementing-the-deref-trait" id="treating-a-type-like-a-reference-by-implementing-the-deref-trait">Treating a Type Like a Reference by Implementing the <code>Deref</code> Trait</a></h3>
<p>As discussed in Chapter 10, to implement a trait, we need to provide
implementations for the traits required methods. The <code>Deref</code> trait, provided
by the standard library, requires us to implement one method named <code>deref</code> that
borrows <code>self</code> and returns a reference to the inner data. Listing 15-10
contains an implementation of <code>Deref</code> to add to the definition of <code>MyBox</code>:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><pre class="playpen"><code class="language-rust">
<span class="boring">#![allow(unused_variables)]
</span><span class="boring">fn main() {
</span>use std::ops::Deref;
<span class="boring">struct MyBox&lt;T&gt;(T);
</span>impl&lt;T&gt; Deref for MyBox&lt;T&gt; {
type Target = T;
fn deref(&amp;self) -&gt; &amp;T {
&amp;self.0
}
}
<span class="boring">}
</span></code></pre></pre>
<p><span class="caption">Listing 15-10: Implementing <code>Deref</code> on <code>MyBox&lt;T&gt;</code></span></p>
<p>The <code>type Target = T;</code> syntax defines an associated type for the <code>Deref</code> trait
to use. Associated types are a slightly different way of declaring a generic
parameter, but you dont need to worry about them for now; well cover them in
more detail in Chapter 19.</p>
<p>We fill in the body of the <code>deref</code> method with <code>&amp;self.0</code> so <code>deref</code> returns a
reference to the value we want to access with the <code>*</code> operator. The <code>main</code>
function in Listing 15-9 that calls <code>*</code> on the <code>MyBox&lt;T&gt;</code> value now compiles,
and the assertions pass!</p>
<p>Without the <code>Deref</code> trait, the compiler can only dereference <code>&amp;</code> references.
The <code>deref</code> method gives the compiler the ability to take a value of any type
that implements <code>Deref</code> and call the <code>deref</code> method to get a <code>&amp;</code> reference that
it knows how to dereference.</p>
<p>When we entered <code>*y</code> in Listing 15-9, behind the scenes Rust actually ran this
code:</p>
<pre><code class="language-rust ignore">*(y.deref())
</code></pre>
<p>Rust substitutes the <code>*</code> operator with a call to the <code>deref</code> method and then a
plain dereference so we dont have to think about whether or not we need to
call the <code>deref</code> method. This Rust feature lets us write code that functions
identically whether we have a regular reference or a type that implements
<code>Deref</code>.</p>
<p>The reason the <code>deref</code> method returns a reference to a value, and that the plain
dereference outside the parentheses in <code>*(y.deref())</code> is still necessary, is the
ownership system. If the <code>deref</code> method returned the value directly instead of
a reference to the value, the value would be moved out of <code>self</code>. We dont want
to take ownership of the inner value inside <code>MyBox&lt;T&gt;</code> in this case or in most
cases where we use the dereference operator.</p>
<p>Note that the <code>*</code> operator is replaced with a call to the <code>deref</code> method and
then a call to the <code>*</code> operator just once, each time we use a <code>*</code> in our code.
Because the substitution of the <code>*</code> operator does not recurse infinitely, we
end up with data of type <code>i32</code>, which matches the <code>5</code> in <code>assert_eq!</code> in
Listing 15-9.</p>
<h3><a class="header" href="#implicit-deref-coercions-with-functions-and-methods" id="implicit-deref-coercions-with-functions-and-methods">Implicit Deref Coercions with Functions and Methods</a></h3>
<p><em>Deref coercion</em> is a convenience that Rust performs on arguments to functions
and methods. Deref coercion converts a reference to a type that implements
<code>Deref</code> into a reference to a type that <code>Deref</code> can convert the original type
into. Deref coercion happens automatically when we pass a reference to a
particular types value as an argument to a function or method that doesnt
match the parameter type in the function or method definition. A sequence of
calls to the <code>deref</code> method converts the type we provided into the type the
parameter needs.</p>
<p>Deref coercion was added to Rust so that programmers writing function and
method calls dont need to add as many explicit references and dereferences
with <code>&amp;</code> and <code>*</code>. The deref coercion feature also lets us write more code that
can work for either references or smart pointers.</p>
<p>To see deref coercion in action, lets use the <code>MyBox&lt;T&gt;</code> type we defined in
Listing 15-8 as well as the implementation of <code>Deref</code> that we added in Listing
15-10. Listing 15-11 shows the definition of a function that has a string slice
parameter:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><pre class="playpen"><code class="language-rust">
<span class="boring">#![allow(unused_variables)]
</span><span class="boring">fn main() {
</span>fn hello(name: &amp;str) {
println!(&quot;Hello, {}!&quot;, name);
}
<span class="boring">}
</span></code></pre></pre>
<p><span class="caption">Listing 15-11: A <code>hello</code> function that has the parameter
<code>name</code> of type <code>&amp;str</code></span></p>
<p>We can call the <code>hello</code> function with a string slice as an argument, such as
<code>hello(&quot;Rust&quot;);</code> for example. Deref coercion makes it possible to call <code>hello</code>
with a reference to a value of type <code>MyBox&lt;String&gt;</code>, as shown in Listing 15-12:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><pre class="playpen"><code class="language-rust"><span class="boring">use std::ops::Deref;
</span><span class="boring">
</span><span class="boring">struct MyBox&lt;T&gt;(T);
</span><span class="boring">
</span><span class="boring">impl&lt;T&gt; MyBox&lt;T&gt; {
</span><span class="boring"> fn new(x: T) -&gt; MyBox&lt;T&gt; {
</span><span class="boring"> MyBox(x)
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">impl&lt;T&gt; Deref for MyBox&lt;T&gt; {
</span><span class="boring"> type Target = T;
</span><span class="boring">
</span><span class="boring"> fn deref(&amp;self) -&gt; &amp;T {
</span><span class="boring"> &amp;self.0
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">fn hello(name: &amp;str) {
</span><span class="boring"> println!(&quot;Hello, {}!&quot;, name);
</span><span class="boring">}
</span><span class="boring">
</span>fn main() {
let m = MyBox::new(String::from(&quot;Rust&quot;));
hello(&amp;m);
}
</code></pre></pre>
<p><span class="caption">Listing 15-12: Calling <code>hello</code> with a reference to a
<code>MyBox&lt;String&gt;</code> value, which works because of deref coercion</span></p>
<p>Here were calling the <code>hello</code> function with the argument <code>&amp;m</code>, which is a
reference to a <code>MyBox&lt;String&gt;</code> value. Because we implemented the <code>Deref</code> trait
on <code>MyBox&lt;T&gt;</code> in Listing 15-10, Rust can turn <code>&amp;MyBox&lt;String&gt;</code> into <code>&amp;String</code>
by calling <code>deref</code>. The standard library provides an implementation of <code>Deref</code>
on <code>String</code> that returns a string slice, and this is in the API documentation
for <code>Deref</code>. Rust calls <code>deref</code> again to turn the <code>&amp;String</code> into <code>&amp;str</code>, which
matches the <code>hello</code> functions definition.</p>
<p>If Rust didnt implement deref coercion, we would have to write the code in
Listing 15-13 instead of the code in Listing 15-12 to call <code>hello</code> with a value
of type <code>&amp;MyBox&lt;String&gt;</code>.</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><pre class="playpen"><code class="language-rust"><span class="boring">use std::ops::Deref;
</span><span class="boring">
</span><span class="boring">struct MyBox&lt;T&gt;(T);
</span><span class="boring">
</span><span class="boring">impl&lt;T&gt; MyBox&lt;T&gt; {
</span><span class="boring"> fn new(x: T) -&gt; MyBox&lt;T&gt; {
</span><span class="boring"> MyBox(x)
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">impl&lt;T&gt; Deref for MyBox&lt;T&gt; {
</span><span class="boring"> type Target = T;
</span><span class="boring">
</span><span class="boring"> fn deref(&amp;self) -&gt; &amp;T {
</span><span class="boring"> &amp;self.0
</span><span class="boring"> }
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">fn hello(name: &amp;str) {
</span><span class="boring"> println!(&quot;Hello, {}!&quot;, name);
</span><span class="boring">}
</span><span class="boring">
</span>fn main() {
let m = MyBox::new(String::from(&quot;Rust&quot;));
hello(&amp;(*m)[..]);
}
</code></pre></pre>
<p><span class="caption">Listing 15-13: The code we would have to write if Rust
didnt have deref coercion</span></p>
<p>The <code>(*m)</code> dereferences the <code>MyBox&lt;String&gt;</code> into a <code>String</code>. Then the <code>&amp;</code> and
<code>[..]</code> take a string slice of the <code>String</code> that is equal to the whole string to
match the signature of <code>hello</code>. The code without deref coercions is harder to
read, write, and understand with all of these symbols involved. Deref coercion
allows Rust to handle these conversions for us automatically.</p>
<p>When the <code>Deref</code> trait is defined for the types involved, Rust will analyze the
types and use <code>Deref::deref</code> as many times as necessary to get a reference to
match the parameters type. The number of times that <code>Deref::deref</code> needs to be
inserted is resolved at compile time, so there is no runtime penalty for taking
advantage of deref coercion!</p>
<h3><a class="header" href="#how-deref-coercion-interacts-with-mutability" id="how-deref-coercion-interacts-with-mutability">How Deref Coercion Interacts with Mutability</a></h3>
<p>Similar to how you use the <code>Deref</code> trait to override the <code>*</code> operator on
immutable references, you can use the <code>DerefMut</code> trait to override the <code>*</code>
operator on mutable references.</p>
<p>Rust does deref coercion when it finds types and trait implementations in three
cases:</p>
<ul>
<li>From <code>&amp;T</code> to <code>&amp;U</code> when <code>T: Deref&lt;Target=U&gt;</code></li>
<li>From <code>&amp;mut T</code> to <code>&amp;mut U</code> when <code>T: DerefMut&lt;Target=U&gt;</code></li>
<li>From <code>&amp;mut T</code> to <code>&amp;U</code> when <code>T: Deref&lt;Target=U&gt;</code></li>
</ul>
<p>The first two cases are the same except for mutability. The first case states
that if you have a <code>&amp;T</code>, and <code>T</code> implements <code>Deref</code> to some type <code>U</code>, you can
get a <code>&amp;U</code> transparently. The second case states that the same deref coercion
happens for mutable references.</p>
<p>The third case is trickier: Rust will also coerce a mutable reference to an
immutable one. But the reverse is <em>not</em> possible: immutable references will
never coerce to mutable references. Because of the borrowing rules, if you have
a mutable reference, that mutable reference must be the only reference to that
data (otherwise, the program wouldnt compile). Converting one mutable
reference to one immutable reference will never break the borrowing rules.
Converting an immutable reference to a mutable reference would require that
there is only one immutable reference to that data, and the borrowing rules
dont guarantee that. Therefore, Rust cant make the assumption that converting
an immutable reference to a mutable reference is possible.</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="ch15-01-box.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="ch15-03-drop.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a href="ch15-01-box.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a href="ch15-03-drop.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script type="text/javascript">
window.playpen_copyable = true;
</script>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
<script type="text/javascript" src="ferris.js"></script>
</body>
</html>