Files
books-futures-explained/book/4_pin.html
Carl Fredrik Samson 15d7c726f8 finished book!!!!!!
2020-04-06 01:51:18 +02:00

896 lines
38 KiB
HTML

<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Pin - Futures Explained in 200 Lines of Rust</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="This book aims to explain Futures in Rust using an example driven approach.">
<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="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" 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 -->
</head>
<body class="light">
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = "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; }
document.body.className = theme;
document.querySelector('html').className = theme + ' 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 class="sidebar-scrollbox">
<ol class="chapter"><li class="affix"><a href="introduction.html">Introduction</a></li><li><a href="0_background_information.html"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html" class="active"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">6.</strong> Futures - our main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html">Conclusion and exercises</a></li></ol>
</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">Futures Explained in 200 Lines of Rust</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>
<a href="https://github.com/cfsamson/books-futures-explained" title="Git repository" aria-label="Git repository">
<i id="git-repository-button" class="fa fa-github"></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>
<h1><a class="header" href="#pin" id="pin">Pin</a></h1>
<blockquote>
<p><strong>Overview</strong></p>
<ol>
<li>Learn how to use <code>Pin</code> and why it's required when implementing your own <code>Future</code></li>
<li>Understand how to make self-referential types safe to use in Rust</li>
<li>Learn how borrowing across <code>await</code> points is accomplished</li>
<li>Get a set of practical rules to help you work with <code>Pin</code></li>
</ol>
<p><code>Pin</code> was suggested in <a href="https://github.com/rust-lang/rfcs/blob/master/text/2349-pin.md">RFC#2349</a></p>
</blockquote>
<p>Let's jump strait to it. Pinning is one of those subjects which is hard to wrap
your head around in the start, but once you unlock a mental model for it
it gets significantly easier to reason about.</p>
<h2><a class="header" href="#definitions" id="definitions">Definitions</a></h2>
<p>Pin is only relevant for pointers. A reference to an object is a pointer.</p>
<p>Pin consists of the <code>Pin</code> type and the <code>Unpin</code> marker. Pin's purpose in life is
to govern the rules that need to apply for types which implement <code>!Unpin</code>.</p>
<p>Yep, you're right, that's double negation right there. <code>!Unpin</code> means
&quot;not-un-pin&quot;.</p>
<blockquote>
<p><em>This naming scheme is one of Rusts safety features where it deliberately
tests if you're too tired to safely implement a type with this marker. If
you're starting to get confused, or even angry, by <code>!Unpin</code> it's a good sign
that it's time to lay down the work and start over tomorrow with a fresh mind.</em></p>
</blockquote>
<p>On a more serious note, I feel obliged to mention that there are valid reasons
for the names that were chosen. Naming is not easy, and I considered renaming
<code>Unpin</code> and <code>!Unpin</code> in this book to make them easier to reason about. </p>
<p>However, an experienced member of the Rust community convinced me that that there
is just too many nuances and edge-cases to consider which is easily overlooked when
naively giving these markers different names, and I'm convinced that we'll
just have to get used to them and use them as is.</p>
<p>If you want to you can read a bit of the discussion from the
<a href="https://internals.rust-lang.org/t/naming-pin-anchor-move/6864/12">internals thread</a>. One of the best takeaways from there in my
eyes is this quote from <code>tmandry</code>:</p>
<blockquote>
<p><em>Think of taking a thumbtack out of a cork board so you can tweak how a flyer
looks. For Unpin types, this unpinning is directly supported by the type; you
can do this implicitly. You can even swap out the object with another before you
put the pin back. For other types, you must be much more careful.</em></p>
</blockquote>
<h2><a class="header" href="#pinning-and-self-referential-structs" id="pinning-and-self-referential-structs">Pinning and self-referential structs</a></h2>
<p>Let's start where we left off in the last chapter by making the problem we
saw using a self-referential struct in our generator a lot simpler by making
some self-referential structs that are easier to reason about than our
state machines:</p>
<p>For now our example will look like this:</p>
<pre><code class="language-rust ignore">use std::pin::Pin;
#[derive(Debug)]
struct Test {
a: String,
b: *const String,
}
impl Test {
fn new(txt: &amp;str) -&gt; Self {
let a = String::from(txt);
Test {
a,
b: std::ptr::null(),
}
}
fn init(&amp;mut self) {
let self_ref: *const String = &amp;self.a;
self.b = self_ref;
}
fn a(&amp;self) -&gt; &amp;str {
&amp;self.a
}
fn b(&amp;self) -&gt; &amp;String {
unsafe {&amp;*(self.b)}
}
}
</code></pre>
<p>Let's walk through this example since we'll be using it the rest of this chapter.</p>
<p>We have a self-referential struct <code>Test</code>. <code>Test</code> needs an <code>init</code> method to be
created which is strange but we'll need that to keep this example as short as
possible.</p>
<p><code>Test</code> provides two methods to get a reference to the value of the fields
<code>a</code> and <code>b</code>. Since <code>b</code> is a reference to <code>a</code> we store it as a pointer since
the borrowing rules of Rust doesn't allow us to define this lifetime.</p>
<p>Now, let's use this example to explain the problem we encounter in detail. As
you see, this works as expected:</p>
<pre><pre class="playpen"><code class="language-rust">fn main() {
let mut test1 = Test::new(&quot;test1&quot;);
test1.init();
let mut test2 = Test::new(&quot;test2&quot;);
test2.init();
println!(&quot;a: {}, b: {}&quot;, test1.a(), test1.b());
println!(&quot;a: {}, b: {}&quot;, test2.a(), test2.b());
}
# use std::pin::Pin;
# #[derive(Debug)]
# struct Test {
# a: String,
# b: *const String,
# }
#
# impl Test {
# fn new(txt: &amp;str) -&gt; Self {
# let a = String::from(txt);
# Test {
# a,
# b: std::ptr::null(),
# }
# }
#
# // We need an `init` method to actually set our self-reference
# fn init(&amp;mut self) {
# let self_ref: *const String = &amp;self.a;
# self.b = self_ref;
# }
#
# fn a(&amp;self) -&gt; &amp;str {
# &amp;self.a
# }
#
# fn b(&amp;self) -&gt; &amp;String {
# unsafe {&amp;*(self.b)}
# }
# }
</code></pre></pre>
<p>In our main method we first instantiate two instances of <code>Test</code> and print out
the value of the fields on <code>test1</code>. We get what we'd expect:</p>
<pre><code class="language-rust ignore">a: test1, b: test1
a: test2, b: test2
</code></pre>
<p>Let's see what happens if we swap the data stored at the memory location
which <code>test1</code> is pointing to with the data stored at the memory location
<code>test2</code> is pointing to and vice a versa.</p>
<pre><pre class="playpen"><code class="language-rust">fn main() {
let mut test1 = Test::new(&quot;test1&quot;);
test1.init();
let mut test2 = Test::new(&quot;test2&quot;);
test2.init();
println!(&quot;a: {}, b: {}&quot;, test1.a(), test1.b());
std::mem::swap(&amp;mut test1, &amp;mut test2);
println!(&quot;a: {}, b: {}&quot;, test2.a(), test2.b());
}
# use std::pin::Pin;
# #[derive(Debug)]
# struct Test {
# a: String,
# b: *const String,
# }
#
# impl Test {
# fn new(txt: &amp;str) -&gt; Self {
# let a = String::from(txt);
# Test {
# a,
# b: std::ptr::null(),
# }
# }
#
# fn init(&amp;mut self) {
# let self_ref: *const String = &amp;self.a;
# self.b = self_ref;
# }
#
# fn a(&amp;self) -&gt; &amp;str {
# &amp;self.a
# }
#
# fn b(&amp;self) -&gt; &amp;String {
# unsafe {&amp;*(self.b)}
# }
# }
</code></pre></pre>
<p>Naively, we could think that what we should get a debug print of <code>test1</code> two
times like this</p>
<pre><code class="language-rust ignore">a: test1, b: test1
a: test1, b: test1
</code></pre>
<p>But instead we get:</p>
<pre><code class="language-rust ignore">a: test1, b: test1
a: test1, b: test2
</code></pre>
<p>The pointer to <code>test2.b</code> still points to the old location which is inside <code>test1</code>
now. The struct is not self-referential anymore, it holds a pointer to a field
in a different object. That means we can't rely on the lifetime of <code>test2.b</code> to
be tied to the lifetime of <code>test2</code> anymore.</p>
<p>If your still not convinced, this should at least convince you:</p>
<pre><pre class="playpen"><code class="language-rust">fn main() {
let mut test1 = Test::new(&quot;test1&quot;);
test1.init();
let mut test2 = Test::new(&quot;test2&quot;);
test2.init();
println!(&quot;a: {}, b: {}&quot;, test1.a(), test1.b());
std::mem::swap(&amp;mut test1, &amp;mut test2);
test1.a = &quot;I've totally changed now!&quot;.to_string();
println!(&quot;a: {}, b: {}&quot;, test2.a(), test2.b());
}
# use std::pin::Pin;
# #[derive(Debug)]
# struct Test {
# a: String,
# b: *const String,
# }
#
# impl Test {
# fn new(txt: &amp;str) -&gt; Self {
# let a = String::from(txt);
# Test {
# a,
# b: std::ptr::null(),
# }
# }
#
# fn init(&amp;mut self) {
# let self_ref: *const String = &amp;self.a;
# self.b = self_ref;
# }
#
# fn a(&amp;self) -&gt; &amp;str {
# &amp;self.a
# }
#
# fn b(&amp;self) -&gt; &amp;String {
# unsafe {&amp;*(self.b)}
# }
# }
</code></pre></pre>
<p>That shouldn't happen. There is no serious error yet, but as you can imagine
it's easy to create serious bugs using this code.</p>
<p>I created a diagram to help visualize what's going on:</p>
<p><strong>Fig 1: Before and after swap</strong>
<img src="./assets/swap_problem.jpg" alt="swap_problem" /></p>
<p>As you can see this results in unwanted behavior. It's easy to get this to
segfault, show UB and fail in other spectacular ways as well.</p>
<h2><a class="header" href="#pinning-to-the-stack" id="pinning-to-the-stack">Pinning to the stack</a></h2>
<p>Now, we can solve this problem by using <code>Pin</code> instead. Let's take a look at what
our example would look like then:</p>
<pre><code class="language-rust ignore">use std::pin::Pin;
use std::marker::PhantomPinned;
#[derive(Debug)]
struct Test {
a: String,
b: *const String,
_marker: PhantomPinned,
}
impl Test {
fn new(txt: &amp;str) -&gt; Self {
let a = String::from(txt);
Test {
a,
b: std::ptr::null(),
// This makes our type `!Unpin`
_marker: PhantomPinned,
}
}
fn init&lt;'a&gt;(self: Pin&lt;&amp;'a mut Self&gt;) {
let self_ptr: *const String = &amp;self.a;
let this = unsafe { self.get_unchecked_mut() };
this.b = self_ptr;
}
fn a&lt;'a&gt;(self: Pin&lt;&amp;'a Self&gt;) -&gt; &amp;'a str {
&amp;self.get_ref().a
}
fn b&lt;'a&gt;(self: Pin&lt;&amp;'a Self&gt;) -&gt; &amp;'a String {
unsafe { &amp;*(self.b) }
}
}
</code></pre>
<p>Now, what we've done here is pinning a stack address. That will always be
<code>unsafe</code> if our type implements <code>!Unpin</code>.</p>
<p>We use the same tricks here, including requiring an <code>init</code>. If we want to fix that
and let users avoid <code>unsafe</code> we need to pin our data on the heap instead which
we'll show in a second.</p>
<p>Let's see what happens if we run our example now:</p>
<pre><pre class="playpen"><code class="language-rust">pub fn main() {
// test1 is safe to move before we initialize it
let mut test1 = Test::new(&quot;test1&quot;);
// Notice how we shadow `test1` to prevent it from beeing accessed again
let mut test1 = unsafe { Pin::new_unchecked(&amp;mut test1) };
Test::init(test1.as_mut());
let mut test2 = Test::new(&quot;test2&quot;);
let mut test2 = unsafe { Pin::new_unchecked(&amp;mut test2) };
Test::init(test2.as_mut());
println!(&quot;a: {}, b: {}&quot;, Test::a(test1.as_ref()), Test::b(test1.as_ref()));
println!(&quot;a: {}, b: {}&quot;, Test::a(test2.as_ref()), Test::b(test2.as_ref()));
}
# use std::pin::Pin;
# use std::marker::PhantomPinned;
#
# #[derive(Debug)]
# struct Test {
# a: String,
# b: *const String,
# _marker: PhantomPinned,
# }
#
#
# impl Test {
# fn new(txt: &amp;str) -&gt; Self {
# let a = String::from(txt);
# Test {
# a,
# b: std::ptr::null(),
# // This makes our type `!Unpin`
# _marker: PhantomPinned,
# }
# }
# fn init&lt;'a&gt;(self: Pin&lt;&amp;'a mut Self&gt;) {
# let self_ptr: *const String = &amp;self.a;
# let this = unsafe { self.get_unchecked_mut() };
# this.b = self_ptr;
# }
#
# fn a&lt;'a&gt;(self: Pin&lt;&amp;'a Self&gt;) -&gt; &amp;'a str {
# &amp;self.get_ref().a
# }
#
# fn b&lt;'a&gt;(self: Pin&lt;&amp;'a Self&gt;) -&gt; &amp;'a String {
# unsafe { &amp;*(self.b) }
# }
# }
</code></pre></pre>
<p>Now, if we try to pull the same trick which got us in to trouble the last time
you'll get a compilation error.</p>
<pre><pre class="playpen"><code class="language-rust compile_fail">pub fn main() {
let mut test1 = Test::new(&quot;test1&quot;);
let mut test1 = unsafe { Pin::new_unchecked(&amp;mut test1) };
Test::init(test1.as_mut());
let mut test2 = Test::new(&quot;test2&quot;);
let mut test2 = unsafe { Pin::new_unchecked(&amp;mut test2) };
Test::init(test2.as_mut());
println!(&quot;a: {}, b: {}&quot;, Test::a(test1.as_ref()), Test::b(test1.as_ref()));
std::mem::swap(test1.as_mut(), test2.as_mut());
println!(&quot;a: {}, b: {}&quot;, Test::a(test2.as_ref()), Test::b(test2.as_ref()));
}
# use std::pin::Pin;
# use std::marker::PhantomPinned;
#
# #[derive(Debug)]
# struct Test {
# a: String,
# b: *const String,
# _marker: PhantomPinned,
# }
#
#
# impl Test {
# fn new(txt: &amp;str) -&gt; Self {
# let a = String::from(txt);
# Test {
# a,
# b: std::ptr::null(),
# // This makes our type `!Unpin`
# _marker: PhantomPinned,
# }
# }
# fn init&lt;'a&gt;(self: Pin&lt;&amp;'a mut Self&gt;) {
# let self_ptr: *const String = &amp;self.a;
# let this = unsafe { self.get_unchecked_mut() };
# this.b = self_ptr;
# }
#
# fn a&lt;'a&gt;(self: Pin&lt;&amp;'a Self&gt;) -&gt; &amp;'a str {
# &amp;self.get_ref().a
# }
#
# fn b&lt;'a&gt;(self: Pin&lt;&amp;'a Self&gt;) -&gt; &amp;'a String {
# unsafe { &amp;*(self.b) }
# }
# }
</code></pre></pre>
<p>As you see from the error you get by running the code the type system prevents
us from swapping the pinned pointers.</p>
<blockquote>
<p>It's important to note that stack pinning will always depend on the current
stack frame we're in, so we can't create a self referential object in one
stack frame and return it since any pointers we take to &quot;self&quot; is invalidated.</p>
<p>It also puts a lot of responsibility in your hands if you pin a value to the
stack. A mistake that is easy to make is, forgetting to shadow the original variable
since you could drop the pinned pointer and access the old value
after it's initialized like this:</p>
<pre><code class="language-rust ignore"> let mut test1 = Test::new(&quot;test1&quot;);
let mut test1_pin = unsafe { Pin::new_unchecked(&amp;mut test1) };
Test::init(test1_pin.as_mut());
drop(test1_pin);
println!(&quot;{:?}&quot;, test1.b);
</code></pre>
</blockquote>
<h2><a class="header" href="#pinning-to-the-heap" id="pinning-to-the-heap">Pinning to the heap</a></h2>
<p>For completeness let's remove some unsafe and the need for an <code>init</code> method
at the cost of a heap allocation. Pinning to the heap is safe so the user
doesn't need to implement any unsafe code:</p>
<pre><pre class="playpen"><code class="language-rust">use std::pin::Pin;
use std::marker::PhantomPinned;
#[derive(Debug)]
struct Test {
a: String,
b: *const String,
_marker: PhantomPinned,
}
impl Test {
fn new(txt: &amp;str) -&gt; Pin&lt;Box&lt;Self&gt;&gt; {
let a = String::from(txt);
let t = Test {
a,
b: std::ptr::null(),
_marker: PhantomPinned,
};
let mut boxed = Box::pin(t);
let self_ptr: *const String = &amp;boxed.as_ref().a;
unsafe { boxed.as_mut().get_unchecked_mut().b = self_ptr };
boxed
}
fn a&lt;'a&gt;(self: Pin&lt;&amp;'a Self&gt;) -&gt; &amp;'a str {
&amp;self.get_ref().a
}
fn b&lt;'a&gt;(self: Pin&lt;&amp;'a Self&gt;) -&gt; &amp;'a String {
unsafe { &amp;*(self.b) }
}
}
pub fn main() {
let mut test1 = Test::new(&quot;test1&quot;);
let mut test2 = Test::new(&quot;test2&quot;);
println!(&quot;a: {}, b: {}&quot;,test1.as_ref().a(), test1.as_ref().b());
println!(&quot;a: {}, b: {}&quot;,test2.as_ref().a(), test2.as_ref().b());
}
</code></pre></pre>
<p>The fact that pinning a heap allocated value that implements <code>!Unpin</code> is safe
makes sense. Once the data is allocated on the heap it will have a stable address.</p>
<p>There is no need for us as users of the API to take special care and ensure
that the self-referential pointer stays valid.</p>
<p>There are ways to safely give some guarantees on stack pinning as well, but right
now you need to use a crate like <a href="https://docs.rs/pin-project/">pin_project</a> to do that.</p>
<h2><a class="header" href="#practical-rules-for-pinning" id="practical-rules-for-pinning">Practical rules for Pinning</a></h2>
<ol>
<li>
<p>If <code>T: Unpin</code> (which is the default), then <code>Pin&lt;'a, T&gt;</code> is entirely
equivalent to <code>&amp;'a mut T</code>. in other words: <code>Unpin</code> means it's OK for this type
to be moved even when pinned, so <code>Pin</code> will have no effect on such a type.</p>
</li>
<li>
<p>Getting a <code>&amp;mut T</code> to a pinned T requires unsafe if <code>T: !Unpin</code>. In
other words: requiring a pinned pointer to a type which is <code>!Unpin</code> prevents
the <em>user</em> of that API from moving that value unless it choses to write <code>unsafe</code>
code.</p>
</li>
<li>
<p>Pinning does nothing special with memory allocation like putting it into some
&quot;read only&quot; memory or anything fancy. It only uses the type system to prevent
certain operations on this value.</p>
</li>
<li>
<p>Most standard library types implement <code>Unpin</code>. The same goes for most
&quot;normal&quot; types you encounter in Rust. <code>Futures</code> and <code>Generators</code> are two
exceptions.</p>
</li>
<li>
<p>The main use case for <code>Pin</code> is to allow self referential types, the whole
justification for stabilizing them was to allow that. There are still corner
cases in the API which are being explored.</p>
</li>
<li>
<p>The implementation behind objects that are <code>!Unpin</code> is most likely unsafe.
Moving such a type after it has been pinned can cause the universe to crash. As of the time of writing
this book, creating and reading fields of a self referential struct still requires <code>unsafe</code>
(the only way to do it is to create a struct containing raw pointers to itself).</p>
</li>
<li>
<p>You can add a <code>!Unpin</code> bound on a type on nightly with a feature flag, or
by adding <code>std::marker::PhantomPinned</code> to your type on stable.</p>
</li>
<li>
<p>You can either pin a value to memory on the stack or on the heap.</p>
</li>
<li>
<p>Pinning a <code>!Unpin</code> pointer to the stack requires <code>unsafe</code></p>
</li>
<li>
<p>Pinning a <code>!Unpin</code> pointer to the heap does not require <code>unsafe</code>. There is a shortcut for doing this using <code>Box::pin</code>.</p>
</li>
</ol>
<blockquote>
<p>Unsafe code does not mean it's literally &quot;unsafe&quot;, it only relieves the
guarantees you normally get from the compiler. An <code>unsafe</code> implementation can
be perfectly safe to do, but you have no safety net.</p>
</blockquote>
<h3><a class="header" href="#projectionstructural-pinning" id="projectionstructural-pinning">Projection/structural pinning</a></h3>
<p>In short, projection is a programming language term. <code>mystruct.field1</code> is a
projection. Structural pinning is using <code>Pin</code> on fields. This has several
caveats and is not something you'll normally see so I refer to the documentation
for that.</p>
<h3><a class="header" href="#pin-and-drop" id="pin-and-drop">Pin and Drop</a></h3>
<p>The <code>Pin</code> guarantee exists from the moment the value is pinned until it's dropped.
In the <code>Drop</code> implementation you take a mutable reference to <code>self</code>, which means
extra care must be taken when implementing <code>Drop</code> for pinned types.</p>
<h2><a class="header" href="#putting-it-all-together" id="putting-it-all-together">Putting it all together</a></h2>
<p>This is exactly what we'll do when we implement our own <code>Futures</code> stay tuned,
we're soon finished.</p>
<h2><a class="header" href="#bonus-section-fixing-our-self-referential-generator-and-learning-more-about-pin" id="bonus-section-fixing-our-self-referential-generator-and-learning-more-about-pin">Bonus section: Fixing our self-referential generator and learning more about Pin</a></h2>
<p>But now, let's prevent this problem using <code>Pin</code>. We'll discuss
<code>Pin</code> more in the next chapter, but you'll get an introduction here by just
reading the comments.</p>
<pre><pre class="playpen"><code class="language-rust">#![feature(optin_builtin_traits, negative_impls)] // needed to implement `!Unpin`
use std::pin::Pin;
pub fn main() {
let gen1 = GeneratorA::start();
let gen2 = GeneratorA::start();
// Before we pin the pointers, this is safe to do
// std::mem::swap(&amp;mut gen, &amp;mut gen2);
// constructing a `Pin::new()` on a type which does not implement `Unpin` is
// unsafe. A value pinned to heap can be constructed while staying in safe
// Rust so we can use that to avoid unsafe. You can also use crates like
// `pin_utils` to pin to the stack safely, just remember that they use
// unsafe under the hood so it's like using an already-reviewed unsafe
// implementation.
let mut pinned1 = Box::pin(gen1);
let mut pinned2 = Box::pin(gen2);
// Uncomment these if you think it's safe to pin the values to the stack instead
// (it is in this case). Remember to comment out the two previous lines first.
//let mut pinned1 = unsafe { Pin::new_unchecked(&amp;mut gen1) };
//let mut pinned2 = unsafe { Pin::new_unchecked(&amp;mut gen2) };
if let GeneratorState::Yielded(n) = pinned1.as_mut().resume() {
println!(&quot;Gen1 got value {}&quot;, n);
}
if let GeneratorState::Yielded(n) = pinned2.as_mut().resume() {
println!(&quot;Gen2 got value {}&quot;, n);
};
// This won't work:
// std::mem::swap(&amp;mut gen, &amp;mut gen2);
// This will work but will just swap the pointers so nothing bad happens here:
// std::mem::swap(&amp;mut pinned1, &amp;mut pinned2);
let _ = pinned1.as_mut().resume();
let _ = pinned2.as_mut().resume();
}
enum GeneratorState&lt;Y, R&gt; {
Yielded(Y),
Complete(R),
}
trait Generator {
type Yield;
type Return;
fn resume(self: Pin&lt;&amp;mut Self&gt;) -&gt; GeneratorState&lt;Self::Yield, Self::Return&gt;;
}
enum GeneratorA {
Enter,
Yield1 {
to_borrow: String,
borrowed: *const String,
},
Exit,
}
impl GeneratorA {
fn start() -&gt; Self {
GeneratorA::Enter
}
}
// This tells us that the underlying pointer is not safe to move after pinning.
// In this case, only we as implementors &quot;feel&quot; this, however, if someone is
// relying on our Pinned pointer this will prevent them from moving it. You need
// to enable the feature flag `#![feature(optin_builtin_traits)]` and use the
// nightly compiler to implement `!Unpin`. Normally, you would use
// `std::marker::PhantomPinned` to indicate that the struct is `!Unpin`.
impl !Unpin for GeneratorA { }
impl Generator for GeneratorA {
type Yield = usize;
type Return = ();
fn resume(self: Pin&lt;&amp;mut Self&gt;) -&gt; GeneratorState&lt;Self::Yield, Self::Return&gt; {
// lets us get ownership over current state
let this = unsafe { self.get_unchecked_mut() };
match this {
GeneratorA::Enter =&gt; {
let to_borrow = String::from(&quot;Hello&quot;);
let borrowed = &amp;to_borrow;
let res = borrowed.len();
*this = GeneratorA::Yield1 {to_borrow, borrowed: std::ptr::null()};
// Trick to actually get a self reference. We can't reference
// the `String` earlier since these references will point to the
// location in this stack frame which will not be valid anymore
// when this function returns.
if let GeneratorA::Yield1 {to_borrow, borrowed} = this {
*borrowed = to_borrow;
}
GeneratorState::Yielded(res)
}
GeneratorA::Yield1 {borrowed, ..} =&gt; {
let borrowed: &amp;String = unsafe {&amp;**borrowed};
println!(&quot;{} world&quot;, borrowed);
*this = GeneratorA::Exit;
GeneratorState::Complete(())
}
GeneratorA::Exit =&gt; panic!(&quot;Can't advance an exited generator!&quot;),
}
}
}
</code></pre></pre>
<p>Now, as you see, the consumer of this API must either:</p>
<ol>
<li>Box the value and thereby allocating it on the heap</li>
<li>Use <code>unsafe</code> and pin the value to the stack. The user knows that if they move
the value afterwards it will violate the guarantee they promise to uphold when
they did their unsafe implementation.</li>
</ol>
<p>Hopefully, after this you'll have an idea of what happens when you use the
<code>yield</code> or <code>await</code> keywords inside an async function, and why we need <code>Pin</code> if
we want to be able to safely borrow across <code>yield/await</code> points.</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="3_generators_pin.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="6_future_example.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="3_generators_pin.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="6_future_example.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>
<!-- Livereload script (if served using the cli tool) -->
<script type="text/javascript">
var socket = new WebSocket("ws://localhost:3001");
socket.onmessage = function (event) {
if (event.data === "reload") {
socket.close();
location.reload(true); // force reload from server (not from cache)
}
};
window.onbeforeunload = function() {
socket.close();
}
</script>
<!-- Google Analytics Tag -->
<script type="text/javascript">
var localAddrs = ["localhost", "127.0.0.1", ""];
// make sure we don't activate google analytics if the developer is
// inspecting the book locally...
if (localAddrs.indexOf(document.location.hostname) === -1) {
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-157536992-1', 'auto');
ga('send', 'pageview');
}
</script>
<script src="ace.js" type="text/javascript" charset="utf-8"></script>
<script src="editor.js" type="text/javascript" charset="utf-8"></script>
<script src="mode-rust.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-dawn.js" type="text/javascript" charset="utf-8"></script>
<script src="theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></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 -->
</body>
</html>