Files
docs-rust/build/ch15-02-deref.html
2026-06-22 21:17:36 +05:30

606 lines
44 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE HTML>
<html lang="en" class="light sidebar-visible" dir="ltr">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Treating Smart Pointers Like Regular References - The Rust Programming Language</title>
<!-- Custom HTML head -->
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
<link rel="icon" href="favicon-de23e50b.svg">
<link rel="shortcut icon" href="favicon-8114d1fc.png">
<link rel="stylesheet" href="css/variables-8adf115d.css">
<link rel="stylesheet" href="css/general-0392ca55.css">
<link rel="stylesheet" href="css/chrome-fc474251.css">
<link rel="stylesheet" href="css/print-9e4910d8.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="fonts/fonts-9644e21d.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" id="mdbook-highlight-css" href="highlight-493f70e1.css">
<link rel="stylesheet" id="mdbook-tomorrow-night-css" href="tomorrow-night-4c0ae647.css">
<link rel="stylesheet" id="mdbook-ayu-highlight-css" href="ayu-highlight-3fdfc3ac.css">
<!-- Custom theme stylesheets -->
<link rel="stylesheet" href="ferris-d33b75bf.css">
<link rel="stylesheet" href="theme/2018-edition-4e126c62.css">
<link rel="stylesheet" href="theme/semantic-notes-9b5766c0.css">
<link rel="stylesheet" href="theme/listing-cab26221.css">
<!-- Provide site root and default themes to javascript -->
<script>
const path_to_root = "";
const default_light_theme = "light";
const default_dark_theme = "navy";
window.path_to_searchindex_js = "searchindex-6a1da8cc.js";
</script>
<!-- Start loading toc.js asap -->
<script src="toc-0e4ce700.js"></script>
</head>
<body>
<div id="mdbook-help-container">
<div id="mdbook-help-popup">
<h2 class="mdbook-help-title">Keyboard shortcuts</h2>
<div>
<p>Press <kbd></kbd> or <kbd></kbd> to navigate between chapters</p>
<p>Press <kbd>S</kbd> or <kbd>/</kbd> to search in the book</p>
<p>Press <kbd>?</kbd> to show this help</p>
<p>Press <kbd>Esc</kbd> to hide this help</p>
</div>
</div>
</div>
<div id="mdbook-body-container">
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script>
try {
let theme = localStorage.getItem('mdbook-theme');
let 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>
const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
let theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
const html = document.documentElement;
html.classList.remove('light')
html.classList.add(theme);
html.classList.add("js");
</script>
<input type="checkbox" id="mdbook-sidebar-toggle-anchor" class="hidden">
<!-- Hide / unhide sidebar before it is displayed -->
<script>
let sidebar = null;
const sidebar_toggle = document.getElementById("mdbook-sidebar-toggle-anchor");
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
sidebar_toggle.checked = false;
}
if (sidebar === 'visible') {
sidebar_toggle.checked = true;
} else {
html.classList.remove('sidebar-visible');
}
</script>
<nav id="mdbook-sidebar" class="sidebar" aria-label="Table of contents">
<!-- populated by js -->
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
<noscript>
<iframe class="sidebar-iframe-outer" src="toc.html"></iframe>
</noscript>
<div id="mdbook-sidebar-resize-handle" class="sidebar-resize-handle">
<div class="sidebar-resize-indicator"></div>
</div>
</nav>
<div id="mdbook-page-wrapper" class="page-wrapper">
<div class="page">
<div id="mdbook-menu-bar-hover-placeholder"></div>
<div id="mdbook-menu-bar" class="menu-bar sticky">
<div class="left-buttons">
<label id="mdbook-sidebar-toggle" class="icon-button" for="mdbook-sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="mdbook-sidebar">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M0 96C0 78.3 14.3 64 32 64H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32C14.3 128 0 113.7 0 96zM0 256c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 416c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg></span>
</label>
<button id="mdbook-theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="mdbook-theme-list">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M371.3 367.1c27.3-3.9 51.9-19.4 67.2-42.9L600.2 74.1c12.6-19.5 9.4-45.3-7.6-61.2S549.7-4.4 531.1 9.6L294.4 187.2c-24 18-38.2 46.1-38.4 76.1L371.3 367.1zm-19.6 25.4l-116-104.4C175.9 290.3 128 339.6 128 400c0 3.9 .2 7.8 .6 11.6c1.8 17.5-10.2 36.4-27.8 36.4H96c-17.7 0-32 14.3-32 32s14.3 32 32 32H240c61.9 0 112-50.1 112-112c0-2.5-.1-5-.2-7.5z"/></svg></span>
</button>
<ul id="mdbook-theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-default_theme">Auto</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-ayu">Ayu</button></li>
</ul>
<button id="mdbook-search-toggle" class="icon-button" type="button" title="Search (`/`)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="/ s" aria-controls="mdbook-searchbar">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352c79.5 0 144-64.5 144-144s-64.5-144-144-144S64 128.5 64 208s64.5 144 144 144z"/></svg></span>
</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">
<span class=fa-svg id="print-button"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M128 0C92.7 0 64 28.7 64 64v96h64V64H354.7L384 93.3V160h64V93.3c0-17-6.7-33.3-18.7-45.3L400 18.7C388 6.7 371.7 0 354.7 0H128zM384 352v32 64H128V384 368 352H384zm64 32h32c17.7 0 32-14.3 32-32V256c0-35.3-28.7-64-64-64H64c-35.3 0-64 28.7-64 64v96c0 17.7 14.3 32 32 32H64v64c0 35.3 28.7 64 64 64H384c35.3 0 64-28.7 64-64V384zm-16-88c-13.3 0-24-10.7-24-24s10.7-24 24-24s24 10.7 24 24s-10.7 24-24 24z"/></svg></span>
</a>
<a href="https://github.com/rust-lang/book" title="Git repository" aria-label="Git repository">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg></span>
</a>
</div>
</div>
<div id="mdbook-search-wrapper" class="hidden">
<form id="mdbook-searchbar-outer" class="searchbar-outer">
<div class="search-wrapper">
<input type="search" id="mdbook-searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="mdbook-searchresults-outer" aria-describedby="searchresults-header">
<div class="spinner-wrapper">
<span class=fa-svg id="fa-spin"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M304 48c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zm0 416c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zM48 304c26.5 0 48-21.5 48-48s-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48zm464-48c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zM142.9 437c18.7-18.7 18.7-49.1 0-67.9s-49.1-18.7-67.9 0s-18.7 49.1 0 67.9s49.1 18.7 67.9 0zm0-294.2c18.7-18.7 18.7-49.1 0-67.9S93.7 56.2 75 75s-18.7 49.1 0 67.9s49.1 18.7 67.9 0zM369.1 437c18.7 18.7 49.1 18.7 67.9 0s18.7-49.1 0-67.9s-49.1-18.7-67.9 0s-18.7 49.1 0 67.9z"/></svg></span>
</div>
</div>
</form>
<div id="mdbook-searchresults-outer" class="searchresults-outer hidden">
<div id="mdbook-searchresults-header" class="searchresults-header"></div>
<ul id="mdbook-searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script>
document.getElementById('mdbook-sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('mdbook-sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#mdbook-sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="mdbook-content" class="content">
<main>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="treating-smart-pointers-like-regular-references-with-the-deref-trait"></a>
<a id="treating-smart-pointers-like-regular-references-with-deref"></a></p>
<h2 id="treating-smart-pointers-like-regular-references"><a class="header" href="#treating-smart-pointers-like-regular-references">Treating Smart Pointers Like Regular References</a></h2>
<p>Implementing the <code>Deref</code> trait allows you to customize the behavior of the
<em>dereference operator</em> <code>*</code> (not to be confused with 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 deref coercion feature and how it lets us work with either references or
smart pointers.</p>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="following-the-pointer-to-the-value-with-the-dereference-operator"></a>
<a id="following-the-pointer-to-the-value"></a></p>
<h3 id="following-the-reference-to-the-value"><a class="header" href="#following-the-reference-to-the-value">Following the Reference to the Value</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 value.</p>
<figure class="listing" id="listing-15-6">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024">fn main() {
let x = 5;
let y = &amp;x;
assert_eq!(5, x);
assert_eq!(5, *y);
}</code></pre>
<figcaption><a href="#listing-15-6">Listing 15-6</a>: Using the dereference operator to follow a reference to an <code>i32</code> value</figcaption>
</figure>
<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>) so that the compiler can
compare the actual value. 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-console">$ cargo run
Compiling deref-example v0.1.0 (file:///projects/deref-example)
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 `PartialEq&lt;&amp;{integer}&gt;` is not implemented for `{integer}`
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
For more information about this error, try `rustc --explain E0277`.
error: could not compile `deref-example` (bin "deref-example") due to 1 previous error
</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 id="using-boxt-like-a-reference"><a class="header" href="#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 used on the <code>Box&lt;T&gt;</code> in Listing 15-7
functions in the same way as the dereference operator used on the reference in
Listing 15-6.</p>
<figure class="listing" id="listing-15-7">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024">fn main() {
let x = 5;
let y = Box::new(x);
assert_eq!(5, x);
assert_eq!(5, *y);
}</code></pre>
<figcaption><a href="#listing-15-7">Listing 15-7</a>: Using the dereference operator on a <code>Box&lt;i32&gt;</code></figcaption>
</figure>
<p>The main 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 a copied value of <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 id="defining-our-own-smart-pointer"><a class="header" href="#defining-our-own-smart-pointer">Defining Our Own Smart Pointer</a></h3>
<p>Lets build a wrapper type similar to the <code>Box&lt;T&gt;</code> type provided by the
standard library to experience how smart pointer types behave differently from
references by default. Then, well look at how to add the ability to use the
dereference operator.</p>
<section class="note" aria-role="note">
<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>
</section>
<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>
<figure class="listing" id="listing-15-8">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024">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><span class="boring">fn main() {}</span></code></pre>
<figcaption><a href="#listing-15-8">Listing 15-8</a>: Defining a <code>MyBox&lt;T&gt;</code> type</figcaption>
</figure>
<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>
<figure class="listing" id="listing-15-9">
<span class="file-name">Filename: src/main.rs</span>
<pre><code class="language-rust ignore does_not_compile"><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>fn main() {
let x = 5;
let y = MyBox::new(x);
assert_eq!(5, x);
assert_eq!(5, *y);
}</code></pre>
<figcaption><a href="#listing-15-9">Listing 15-9</a>: Attempting to use <code>MyBox&lt;T&gt;</code> in the same way we used references and <code>Box&lt;T&gt;</code></figcaption>
</figure>
<p>Heres the resultant compilation error:</p>
<pre><code class="language-console">$ cargo run
Compiling deref-example v0.1.0 (file:///projects/deref-example)
error[E0614]: type `MyBox&lt;{integer}&gt;` cannot be dereferenced
--&gt; src/main.rs:14:19
|
14 | assert_eq!(5, *y);
| ^^ can't be dereferenced
For more information about this error, try `rustc --explain E0614`.
error: could not compile `deref-example` (bin "deref-example") due to 1 previous error
</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>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="treating-a-type-like-a-reference-by-implementing-the-deref-trait"></a></p>
<h3 id="implementing-the-deref-trait"><a class="header" href="#implementing-the-deref-trait">Implementing the <code>Deref</code> Trait</a></h3>
<p>As discussed in <a href="ch10-02-traits.html#implementing-a-trait-on-a-type">“Implementing a Trait on a Type”</a><!-- ignore --> 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&lt;T&gt;</code>.</p>
<figure class="listing" id="listing-15-10">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024">use std::ops::Deref;
impl&lt;T&gt; Deref for MyBox&lt;T&gt; {
type Target = T;
fn deref(&amp;self) -&gt; &amp;Self::Target {
&amp;self.0
}
}
<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">fn main() {
</span><span class="boring"> let x = 5;
</span><span class="boring"> let y = MyBox::new(x);
</span><span class="boring">
</span><span class="boring"> assert_eq!(5, x);
</span><span class="boring"> assert_eq!(5, *y);
</span><span class="boring">}</span></code></pre>
<figcaption><a href="#listing-15-10">Listing 15-10</a>: Implementing <code>Deref</code> on <code>MyBox&lt;T&gt;</code></figcaption>
</figure>
<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 20.</p>
<p>We fill in the body of the <code>deref</code> method with <code>&amp;self.0</code> so that <code>deref</code>
returns a reference to the value we want to access with the <code>*</code> operator;
recall from <a href="ch05-01-defining-structs.html#creating-different-types-with-tuple-structs">“Creating Different Types with Tuple Structs”</a><!--
ignore --> in Chapter 5 that <code>.0</code> accesses the first value in a tuple struct.
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 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 that 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,
has to do with 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>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="implicit-deref-coercions-with-functions-and-methods"></a>
<a id="using-deref-coercions-in-functions-and-methods"></a></p>
<h3 id="using-deref-coercion-in-functions-and-methods"><a class="header" href="#using-deref-coercion-in-functions-and-methods">Using Deref Coercion in Functions and Methods</a></h3>
<p><em>Deref coercion</em> converts a reference to a type that implements the <code>Deref</code>
trait into a reference to another type. For example, deref coercion can convert
<code>&amp;String</code> to <code>&amp;str</code> because <code>String</code> implements the <code>Deref</code> trait such that it
returns <code>&amp;str</code>. Deref coercion is a convenience Rust performs on arguments to
functions and methods, and it works only on types that implement the <code>Deref</code>
trait. It 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>
<figure class="listing" id="listing-15-11">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024">fn hello(name: &amp;str) {
println!("Hello, {name}!");
}
<span class="boring">
</span><span class="boring">fn main() {}</span></code></pre>
<figcaption><a href="#listing-15-11">Listing 15-11</a>: A <code>hello</code> function that has the parameter <code>name</code> of type <code>&amp;str</code></figcaption>
</figure>
<p>We can call the <code>hello</code> function with a string slice as an argument, such as
<code>hello("Rust");</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>
<figure class="listing" id="listing-15-12">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024"><span class="boring">use std::ops::Deref;
</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">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">fn hello(name: &amp;str) {
</span><span class="boring"> println!("Hello, {name}!");
</span><span class="boring">}
</span><span class="boring">
</span>fn main() {
let m = MyBox::new(String::from("Rust"));
hello(&amp;m);
}</code></pre>
<figcaption><a href="#listing-15-12">Listing 15-12</a>: Calling <code>hello</code> with a reference to a <code>MyBox&lt;String&gt;</code> value, which works because of deref coercion</figcaption>
</figure>
<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>
<figure class="listing" id="listing-15-13">
<span class="file-name">Filename: src/main.rs</span>
<pre class="playground"><code class="language-rust edition2024"><span class="boring">use std::ops::Deref;
</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">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">fn hello(name: &amp;str) {
</span><span class="boring"> println!("Hello, {name}!");
</span><span class="boring">}
</span><span class="boring">
</span>fn main() {
let m = MyBox::new(String::from("Rust"));
hello(&amp;(*m)[..]);
}</code></pre>
<figcaption><a href="#listing-15-13">Listing 15-13</a>: The code we would have to write if Rust didnt have deref coercion</figcaption>
</figure>
<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>. This code without deref coercions is harder to
read, write, and understand with all of these symbols involved. Deref coercion
allows Rust to handle these conversions for us automatically.</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>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="how-deref-coercion-interacts-with-mutability"></a></p>
<h3 id="handling-deref-coercion-with-mutable-references"><a class="header" href="#handling-deref-coercion-with-mutable-references">Handling Deref Coercion with Mutable References</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>
<ol>
<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>
</ol>
<p>The first two cases are the same except that the second implements 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 the
initial immutable reference is the only immutable reference to that data, but
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">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M41.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l160 160c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L109.3 256 246.6 118.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-160 160z"/></svg></span>
</a>
<a rel="next prefetch" href="ch15-03-drop.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M278.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-160 160c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L210.7 256 73.4 118.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l160 160z"/></svg></span>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="ch15-01-box.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M41.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l160 160c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L109.3 256 246.6 118.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-160 160z"/></svg></span>
</a>
<a rel="next prefetch" href="ch15-03-drop.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M278.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-160 160c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L210.7 256 73.4 118.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l160 160z"/></svg></span>
</a>
</nav>
</div>
<template id=fa-eye><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z"/></svg></span></template>
<template id=fa-eye-slash><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z"/></svg></span></template>
<template id=fa-copy><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M502.6 70.63l-61.25-61.25C435.4 3.371 427.2 0 418.7 0H255.1c-35.35 0-64 28.66-64 64l.0195 256C192 355.4 220.7 384 256 384h192c35.2 0 64-28.8 64-64V93.25C512 84.77 508.6 76.63 502.6 70.63zM464 320c0 8.836-7.164 16-16 16H255.1c-8.838 0-16-7.164-16-16L239.1 64.13c0-8.836 7.164-16 16-16h128L384 96c0 17.67 14.33 32 32 32h47.1V320zM272 448c0 8.836-7.164 16-16 16H63.1c-8.838 0-16-7.164-16-16L47.98 192.1c0-8.836 7.164-16 16-16H160V128H63.99c-35.35 0-64 28.65-64 64l.0098 256C.002 483.3 28.66 512 64 512h192c35.2 0 64-28.8 64-64v-32h-47.1L272 448z"/></svg></span></template>
<template id=fa-play><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M73 39c-14.8-9.1-33.4-9.4-48.5-.9S0 62.6 0 80V432c0 17.4 9.4 33.4 24.5 41.9s33.7 8.1 48.5-.9L361 297c14.3-8.7 23-24.2 23-41s-8.7-32.2-23-41L73 39z"/></svg></span></template>
<template id=fa-clock-rotate-left><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M75 75L41 41C25.9 25.9 0 36.6 0 57.9V168c0 13.3 10.7 24 24 24H134.1c21.4 0 32.1-25.9 17-41l-30.8-30.8C155 85.5 203 64 256 64c106 0 192 86 192 192s-86 192-192 192c-40.8 0-78.6-12.7-109.7-34.4c-14.5-10.1-34.4-6.6-44.6 7.9s-6.6 34.4 7.9 44.6C151.2 495 201.7 512 256 512c141.4 0 256-114.6 256-256S397.4 0 256 0C185.3 0 121.3 28.7 75 75zm181 53c-13.3 0-24 10.7-24 24V256c0 6.4 2.5 12.5 7 17l72 72c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-65-65V152c0-13.3-10.7-24-24-24z"/></svg></span></template>
<script>
window.playground_copyable = true;
</script>
<script src="elasticlunr-ef4e11c1.min.js"></script>
<script src="mark-09e88c2c.min.js"></script>
<script src="searcher-09f2665d.js"></script>
<script src="clipboard-1626706a.min.js"></script>
<script src="highlight-abc7f01d.js"></script>
<script src="book-c22b7243.js"></script>
<!-- Custom JS scripts -->
<script src="ferris-2317480c.js"></script>
</div>
</body>
</html>