fix outdated links re: #13

This commit is contained in:
Carl Fredrik Samson
2020-04-18 02:28:53 +02:00
parent a4c161c060
commit f4deaaf87b
20 changed files with 1647 additions and 1900 deletions

View File

@@ -1,5 +1,5 @@
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
<html lang="en" class="sidebar-visible no-js">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
@@ -32,11 +32,11 @@
</head>
<body>
<body class="light">
<!-- 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";
var default_theme = "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
@@ -60,11 +60,8 @@
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');
document.body.className = theme;
document.querySelector('html').className = theme + ' js';
</script>
<!-- Hide / unhide sidebar before it is displayed -->
@@ -80,8 +77,8 @@
</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="introduction.html">Introduction</a></li><li class="expanded "><a href="0_background_information.html"><strong aria-hidden="true">1.</strong> Background information</a></li><li class="expanded "><a href="1_futures_in_rust.html"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li class="expanded "><a href="2_waker_context.html"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li class="expanded "><a href="3_generators_async_await.html"><strong aria-hidden="true">4.</strong> Generators and async/await</a></li><li class="expanded "><a href="4_pin.html" class="active"><strong aria-hidden="true">5.</strong> Pin</a></li><li class="expanded "><a href="6_future_example.html"><strong aria-hidden="true">6.</strong> Implementing Futures</a></li><li class="expanded "><a href="8_finished_example.html"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="expanded affix "><a href="conclusion.html">Conclusion and exercises</a></li></ol>
<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_async_await.html"><strong aria-hidden="true">4.</strong> Generators and async/await</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> Implementing Futures</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>
@@ -167,7 +164,9 @@
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 wraps a pointer. A reference to an object is a pointer. Pin gives some
guarantees about the <em>pointee</em> (the data it points to) which we'll explore further
in this chapter.</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
@@ -189,7 +188,7 @@ just have to get used to them and use them as is.</p>
<a href="https://internals.rust-lang.org/t/naming-pin-anchor-move/6864/12">internals thread</a>.</p>
<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
saw using a self-references 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>
@@ -242,45 +241,44 @@ you see, this works as expected:</p>
println!(&quot;a: {}, b: {}&quot;, test2.a(), test2.b());
}
<span class="boring">use std::pin::Pin;
</span><span class="boring">#[derive(Debug)]
</span><span class="boring">struct Test {
</span><span class="boring"> a: String,
</span><span class="boring"> b: *const String,
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">impl Test {
</span><span class="boring"> fn new(txt: &amp;str) -&gt; Self {
</span><span class="boring"> let a = String::from(txt);
</span><span class="boring"> Test {
</span><span class="boring"> a,
</span><span class="boring"> b: std::ptr::null(),
</span><span class="boring"> }
</span><span class="boring"> }
</span><span class="boring">
</span><span class="boring"> // We need an `init` method to actually set our self-reference
</span><span class="boring"> fn init(&amp;mut self) {
</span><span class="boring"> let self_ref: *const String = &amp;self.a;
</span><span class="boring"> self.b = self_ref;
</span><span class="boring"> }
</span><span class="boring">
</span><span class="boring"> fn a(&amp;self) -&gt; &amp;str {
</span><span class="boring"> &amp;self.a
</span><span class="boring"> }
</span><span class="boring">
</span><span class="boring"> fn b(&amp;self) -&gt; &amp;String {
</span><span class="boring"> unsafe {&amp;*(self.b)}
</span><span class="boring"> }
</span><span class="boring">}
</span></code></pre></pre>
# 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>
<p>Let's see what happens if we swap the data stored at the memory location <code>test1</code> with the
data stored at the memory location <code>test2</code> 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();
@@ -292,36 +290,36 @@ which <code>test1</code> is pointing to with the data stored at the memory locat
println!(&quot;a: {}, b: {}&quot;, test2.a(), test2.b());
}
<span class="boring">use std::pin::Pin;
</span><span class="boring">#[derive(Debug)]
</span><span class="boring">struct Test {
</span><span class="boring"> a: String,
</span><span class="boring"> b: *const String,
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">impl Test {
</span><span class="boring"> fn new(txt: &amp;str) -&gt; Self {
</span><span class="boring"> let a = String::from(txt);
</span><span class="boring"> Test {
</span><span class="boring"> a,
</span><span class="boring"> b: std::ptr::null(),
</span><span class="boring"> }
</span><span class="boring"> }
</span><span class="boring">
</span><span class="boring"> fn init(&amp;mut self) {
</span><span class="boring"> let self_ref: *const String = &amp;self.a;
</span><span class="boring"> self.b = self_ref;
</span><span class="boring"> }
</span><span class="boring">
</span><span class="boring"> fn a(&amp;self) -&gt; &amp;str {
</span><span class="boring"> &amp;self.a
</span><span class="boring"> }
</span><span class="boring">
</span><span class="boring"> fn b(&amp;self) -&gt; &amp;String {
</span><span class="boring"> unsafe {&amp;*(self.b)}
</span><span class="boring"> }
</span><span class="boring">}
</span></code></pre></pre>
# 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
@@ -348,36 +346,36 @@ be tied to the lifetime of <code>test2</code> anymore.</p>
println!(&quot;a: {}, b: {}&quot;, test2.a(), test2.b());
}
<span class="boring">use std::pin::Pin;
</span><span class="boring">#[derive(Debug)]
</span><span class="boring">struct Test {
</span><span class="boring"> a: String,
</span><span class="boring"> b: *const String,
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">impl Test {
</span><span class="boring"> fn new(txt: &amp;str) -&gt; Self {
</span><span class="boring"> let a = String::from(txt);
</span><span class="boring"> Test {
</span><span class="boring"> a,
</span><span class="boring"> b: std::ptr::null(),
</span><span class="boring"> }
</span><span class="boring"> }
</span><span class="boring">
</span><span class="boring"> fn init(&amp;mut self) {
</span><span class="boring"> let self_ref: *const String = &amp;self.a;
</span><span class="boring"> self.b = self_ref;
</span><span class="boring"> }
</span><span class="boring">
</span><span class="boring"> fn a(&amp;self) -&gt; &amp;str {
</span><span class="boring"> &amp;self.a
</span><span class="boring"> }
</span><span class="boring">
</span><span class="boring"> fn b(&amp;self) -&gt; &amp;String {
</span><span class="boring"> unsafe {&amp;*(self.b)}
</span><span class="boring"> }
</span><span class="boring">}
</span></code></pre></pre>
# 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>
@@ -423,7 +421,7 @@ impl Test {
}
}
</code></pre>
<p>Now, what we've done here is pinning a stack address. That will always be
<p>Now, what we've done here is pinning an object to the stack. 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
@@ -443,42 +441,42 @@ we'll show in a second.</p>
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()));
}
<span class="boring">use std::pin::Pin;
</span><span class="boring">use std::marker::PhantomPinned;
</span><span class="boring">
</span><span class="boring">#[derive(Debug)]
</span><span class="boring">struct Test {
</span><span class="boring"> a: String,
</span><span class="boring"> b: *const String,
</span><span class="boring"> _marker: PhantomPinned,
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">
</span><span class="boring">impl Test {
</span><span class="boring"> fn new(txt: &amp;str) -&gt; Self {
</span><span class="boring"> let a = String::from(txt);
</span><span class="boring"> Test {
</span><span class="boring"> a,
</span><span class="boring"> b: std::ptr::null(),
</span><span class="boring"> // This makes our type `!Unpin`
</span><span class="boring"> _marker: PhantomPinned,
</span><span class="boring"> }
</span><span class="boring"> }
</span><span class="boring"> fn init&lt;'a&gt;(self: Pin&lt;&amp;'a mut Self&gt;) {
</span><span class="boring"> let self_ptr: *const String = &amp;self.a;
</span><span class="boring"> let this = unsafe { self.get_unchecked_mut() };
</span><span class="boring"> this.b = self_ptr;
</span><span class="boring"> }
</span><span class="boring">
</span><span class="boring"> fn a&lt;'a&gt;(self: Pin&lt;&amp;'a Self&gt;) -&gt; &amp;'a str {
</span><span class="boring"> &amp;self.get_ref().a
</span><span class="boring"> }
</span><span class="boring">
</span><span class="boring"> fn b&lt;'a&gt;(self: Pin&lt;&amp;'a Self&gt;) -&gt; &amp;'a String {
</span><span class="boring"> unsafe { &amp;*(self.b) }
</span><span class="boring"> }
</span><span class="boring">}
</span></code></pre></pre>
# 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() {
@@ -494,50 +492,50 @@ you'll get a compilation error.</p>
std::mem::swap(test1.get_mut(), test2.get_mut());
println!(&quot;a: {}, b: {}&quot;, Test::a(test2.as_ref()), Test::b(test2.as_ref()));
}
<span class="boring">use std::pin::Pin;
</span><span class="boring">use std::marker::PhantomPinned;
</span><span class="boring">
</span><span class="boring">#[derive(Debug)]
</span><span class="boring">struct Test {
</span><span class="boring"> a: String,
</span><span class="boring"> b: *const String,
</span><span class="boring"> _marker: PhantomPinned,
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">
</span><span class="boring">impl Test {
</span><span class="boring"> fn new(txt: &amp;str) -&gt; Self {
</span><span class="boring"> Test {
</span><span class="boring"> a: let a = String::from(txt),
</span><span class="boring"> b: std::ptr::null(),
</span><span class="boring"> _marker: PhantomPinned, // This makes our type `!Unpin`
</span><span class="boring"> }
</span><span class="boring"> }
</span><span class="boring"> fn init&lt;'a&gt;(self: Pin&lt;&amp;'a mut Self&gt;) {
</span><span class="boring"> let self_ptr: *const String = &amp;self.a;
</span><span class="boring"> let this = unsafe { self.get_unchecked_mut() };
</span><span class="boring"> this.b = self_ptr;
</span><span class="boring"> }
</span><span class="boring">
</span><span class="boring"> fn a&lt;'a&gt;(self: Pin&lt;&amp;'a Self&gt;) -&gt; &amp;'a str {
</span><span class="boring"> &amp;self.get_ref().a
</span><span class="boring"> }
</span><span class="boring">
</span><span class="boring"> fn b&lt;'a&gt;(self: Pin&lt;&amp;'a Self&gt;) -&gt; &amp;'a String {
</span><span class="boring"> unsafe { &amp;*(self.b) }
</span><span class="boring"> }
</span><span class="boring">}
</span></code></pre></pre>
# 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 {
# Test {
# a: let a = String::from(txt),
# b: std::ptr::null(),
# _marker: PhantomPinned, // This makes our type `!Unpin`
# }
# }
# 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
<p>It also puts a lot of responsibility in your hands if you pin an object 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>
since you could drop the <code>Pin</code> and access the old value after it's initialized
like this:</p>
<pre><pre class="playpen"><code class="language-rust">fn main() {
let mut test1 = Test::new(&quot;test1&quot;);
let mut test1_pin = unsafe { Pin::new_unchecked(&amp;mut test1) };
@@ -548,41 +546,41 @@ after it's initialized like this:</p>
mem::swap(&amp;mut test1, &amp;mut test2);
println!(&quot;Not self referential anymore: {:?}&quot;, test1.b);
}
<span class="boring">use std::pin::Pin;
</span><span class="boring">use std::marker::PhantomPinned;
</span><span class="boring">use std::mem;
</span><span class="boring">
</span><span class="boring">#[derive(Debug)]
</span><span class="boring">struct Test {
</span><span class="boring"> a: String,
</span><span class="boring"> b: *const String,
</span><span class="boring"> _marker: PhantomPinned,
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">
</span><span class="boring">impl Test {
</span><span class="boring"> fn new(txt: &amp;str) -&gt; Self {
</span><span class="boring"> Test {
</span><span class="boring"> a: String::from(txt),
</span><span class="boring"> b: std::ptr::null(),
</span><span class="boring"> _marker: PhantomPinned, // This makes our type `!Unpin`
</span><span class="boring"> }
</span><span class="boring"> }
</span><span class="boring"> fn init&lt;'a&gt;(self: Pin&lt;&amp;'a mut Self&gt;) {
</span><span class="boring"> let self_ptr: *const String = &amp;self.a;
</span><span class="boring"> let this = unsafe { self.get_unchecked_mut() };
</span><span class="boring"> this.b = self_ptr;
</span><span class="boring"> }
</span><span class="boring">
</span><span class="boring"> fn a&lt;'a&gt;(self: Pin&lt;&amp;'a Self&gt;) -&gt; &amp;'a str {
</span><span class="boring"> &amp;self.get_ref().a
</span><span class="boring"> }
</span><span class="boring">
</span><span class="boring"> fn b&lt;'a&gt;(self: Pin&lt;&amp;'a Self&gt;) -&gt; &amp;'a String {
</span><span class="boring"> unsafe { &amp;*(self.b) }
</span><span class="boring"> }
</span><span class="boring">}
</span></code></pre></pre>
# use std::pin::Pin;
# use std::marker::PhantomPinned;
# use std::mem;
#
# #[derive(Debug)]
# struct Test {
# a: String,
# b: *const String,
# _marker: PhantomPinned,
# }
#
#
# impl Test {
# fn new(txt: &amp;str) -&gt; Self {
# Test {
# a: String::from(txt),
# b: std::ptr::null(),
# _marker: PhantomPinned, // This makes our type `!Unpin`
# }
# }
# 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>
</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
@@ -629,7 +627,7 @@ pub fn main() {
println!(&quot;a: {}, b: {}&quot;,test2.as_ref().a(), test2.as_ref().b());
}
</code></pre></pre>
<p>The fact that it's safe to pin a heap allocated value even if it is <code>!Unpin</code>
<p>The fact that it's safe to pin heap allocated data even if it is <code>!Unpin</code>
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>
@@ -660,8 +658,7 @@ 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>
justification for stabilizing them was to allow that.</p>
</li>
<li>
<p>The implementation behind objects that are <code>!Unpin</code> is most likely unsafe.
@@ -674,13 +671,13 @@ this book, creating and reading fields of a self referential struct still requir
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>
<p>You can either pin an object to the stack or to the heap.</p>
</li>
<li>
<p>Pinning a <code>!Unpin</code> pointer to the stack requires <code>unsafe</code></p>
<p>Pinning a <code>!Unpin</code> object 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>
<p>Pinning a <code>!Unpin</code> object 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>
@@ -709,11 +706,11 @@ 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
// Before we pin the data, 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
// unsafe. An object 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
@@ -770,9 +767,9 @@ impl GeneratorA {
}
}
// This tells us that the underlying pointer is not safe to move after pinning.
// This tells us that this object 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
// relying on our Pinned data 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`.
@@ -898,18 +895,6 @@ we want to be able to safely borrow across <code>yield/await</code> points.</p>
<script type="text/javascript">
window.playpen_line_numbers = true;
</script>
<script type="text/javascript">
window.playpen_copyable = true;
</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>