merged version 3

This commit is contained in:
Carl Fredrik Samson
2020-04-05 18:32:42 +02:00
7 changed files with 43 additions and 31 deletions

View File

@@ -345,13 +345,10 @@ machine for the generator defined aboce.</p>
<p>We step through each step &quot;manually&quot; in every example, so it looks pretty <p>We step through each step &quot;manually&quot; in every example, so it looks pretty
unfamiliar. We could add some syntactic sugar like implementing the <code>Iterator</code> unfamiliar. We could add some syntactic sugar like implementing the <code>Iterator</code>
trait for our generators which would let us do this:</p> trait for our generators which would let us do this:</p>
<pre><pre class="playpen"><code class="language-rust ingore"> <pre><code class="language-rust ignore">for val in generator {
# #![allow(unused_variables)]
#fn main() {
for val in generator {
println!(&quot;{}&quot;, val); println!(&quot;{}&quot;, val);
} }
#}</code></pre></pre> </code></pre>
<p>It's a pretty trivial change to make, but this chapter is already getting long. <p>It's a pretty trivial change to make, but this chapter is already getting long.
Just keep this in the back of your head as we move forward.</p> Just keep this in the back of your head as we move forward.</p>
<p>Now what does our rewritten state machine look like with this example?</p> <p>Now what does our rewritten state machine look like with this example?</p>
@@ -556,7 +553,9 @@ one huge problem with this:</p>
</code></pre></pre> </code></pre></pre>
<p>The problem however is that in safe Rust we can still do this:</p> <p>The problem however is that in safe Rust we can still do this:</p>
<p><em>Run the code and compare the results. Do you see the problem?</em></p> <p><em>Run the code and compare the results. Do you see the problem?</em></p>
<pre><pre class="playpen"><code class="language-rust">pub fn main() { <pre><pre class="playpen"><code class="language-rust should_panic"># #![feature(never_type)] // Force nightly compiler to be used in playground
# // by betting on it's true that this type is named after it's stabilization date...
pub fn main() {
let mut gen = GeneratorA::start(); let mut gen = GeneratorA::start();
let mut gen2 = GeneratorA::start(); let mut gen2 = GeneratorA::start();
@@ -631,10 +630,15 @@ one huge problem with this:</p>
# } # }
</code></pre></pre> </code></pre></pre>
<p>Wait? What happened to &quot;Hello&quot;?</p> <p>Wait? What happened to &quot;Hello&quot;?</p>
<p>Turns out that while the example above compiles <p>Turns out that while the example above compiles just fine, we expose consumers
just fine, we expose consumers of this this API to both possible undefined of this this API to both possible undefined behavior and other memory errors
behavior and other memory errors while using just safe Rust. This is a big while using just safe Rust. This is a big problem!</p>
problem!</p> <blockquote>
<p>I've actually forced the code above to use the nightly version of the compiler.
If you run <a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=5cbe9897c0e23a502afd2740c7e78b98">the example above on the playground</a>,
you'll see that it runs without panic on the current stable (1.42.0) but
panics on the current nightly (1.44.0). Scary!</p>
</blockquote>
<p>We'll explain exactly what happened using a slightly simpler example in the next <p>We'll explain exactly what happened using a slightly simpler example in the next
chapter and we'll fix our generator using <code>Pin</code> so join me as we explore chapter and we'll fix our generator using <code>Pin</code> so join me as we explore
the last topic before we implement our main Futures example.</p> the last topic before we implement our main Futures example.</p>

View File

@@ -746,7 +746,7 @@ impl Generator for GeneratorA {
// the `String` earlier since these references will point to the // the `String` earlier since these references will point to the
// location in this stack frame which will not be valid anymore // location in this stack frame which will not be valid anymore
// when this function returns. // when this function returns.
if let GeneratorA::Yield1 {to_borrow, borrowed} = self { if let GeneratorA::Yield1 {to_borrow, borrowed} = this {
*borrowed = to_borrow; *borrowed = to_borrow;
} }

View File

@@ -1175,13 +1175,10 @@ machine for the generator defined aboce.</p>
<p>We step through each step &quot;manually&quot; in every example, so it looks pretty <p>We step through each step &quot;manually&quot; in every example, so it looks pretty
unfamiliar. We could add some syntactic sugar like implementing the <code>Iterator</code> unfamiliar. We could add some syntactic sugar like implementing the <code>Iterator</code>
trait for our generators which would let us do this:</p> trait for our generators which would let us do this:</p>
<pre><pre class="playpen"><code class="language-rust ingore"> <pre><code class="language-rust ignore">for val in generator {
# #![allow(unused_variables)]
#fn main() {
for val in generator {
println!(&quot;{}&quot;, val); println!(&quot;{}&quot;, val);
} }
#}</code></pre></pre> </code></pre>
<p>It's a pretty trivial change to make, but this chapter is already getting long. <p>It's a pretty trivial change to make, but this chapter is already getting long.
Just keep this in the back of your head as we move forward.</p> Just keep this in the back of your head as we move forward.</p>
<p>Now what does our rewritten state machine look like with this example?</p> <p>Now what does our rewritten state machine look like with this example?</p>
@@ -1386,7 +1383,9 @@ one huge problem with this:</p>
</code></pre></pre> </code></pre></pre>
<p>The problem however is that in safe Rust we can still do this:</p> <p>The problem however is that in safe Rust we can still do this:</p>
<p><em>Run the code and compare the results. Do you see the problem?</em></p> <p><em>Run the code and compare the results. Do you see the problem?</em></p>
<pre><pre class="playpen"><code class="language-rust">pub fn main() { <pre><pre class="playpen"><code class="language-rust should_panic"># #![feature(never_type)] // Force nightly compiler to be used in playground
# // by betting on it's true that this type is named after it's stabilization date...
pub fn main() {
let mut gen = GeneratorA::start(); let mut gen = GeneratorA::start();
let mut gen2 = GeneratorA::start(); let mut gen2 = GeneratorA::start();
@@ -1461,10 +1460,15 @@ one huge problem with this:</p>
# } # }
</code></pre></pre> </code></pre></pre>
<p>Wait? What happened to &quot;Hello&quot;?</p> <p>Wait? What happened to &quot;Hello&quot;?</p>
<p>Turns out that while the example above compiles <p>Turns out that while the example above compiles just fine, we expose consumers
just fine, we expose consumers of this this API to both possible undefined of this this API to both possible undefined behavior and other memory errors
behavior and other memory errors while using just safe Rust. This is a big while using just safe Rust. This is a big problem!</p>
problem!</p> <blockquote>
<p>I've actually forced the code above to use the nightly version of the compiler.
If you run <a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=5cbe9897c0e23a502afd2740c7e78b98">the example above on the playground</a>,
you'll see that it runs without panic on the current stable (1.42.0) but
panics on the current nightly (1.44.0). Scary!</p>
</blockquote>
<p>We'll explain exactly what happened using a slightly simpler example in the next <p>We'll explain exactly what happened using a slightly simpler example in the next
chapter and we'll fix our generator using <code>Pin</code> so join me as we explore chapter and we'll fix our generator using <code>Pin</code> so join me as we explore
the last topic before we implement our main Futures example.</p> the last topic before we implement our main Futures example.</p>
@@ -2109,7 +2113,7 @@ impl Generator for GeneratorA {
// the `String` earlier since these references will point to the // the `String` earlier since these references will point to the
// location in this stack frame which will not be valid anymore // location in this stack frame which will not be valid anymore
// when this function returns. // when this function returns.
if let GeneratorA::Yield1 {to_borrow, borrowed} = self { if let GeneratorA::Yield1 {to_borrow, borrowed} = this {
*borrowed = to_borrow; *borrowed = to_borrow;
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -222,7 +222,7 @@ We step through each step "manually" in every example, so it looks pretty
unfamiliar. We could add some syntactic sugar like implementing the `Iterator` unfamiliar. We could add some syntactic sugar like implementing the `Iterator`
trait for our generators which would let us do this: trait for our generators which would let us do this:
```rust, ingore ```rust, ignore
for val in generator { for val in generator {
println!("{}", val); println!("{}", val);
} }
@@ -447,7 +447,9 @@ pub fn main() {
The problem however is that in safe Rust we can still do this: The problem however is that in safe Rust we can still do this:
_Run the code and compare the results. Do you see the problem?_ _Run the code and compare the results. Do you see the problem?_
```rust ```rust, should_panic
# #![feature(never_type)] // Force nightly compiler to be used in playground
# // by betting on it's true that this type is named after it's stabilization date...
pub fn main() { pub fn main() {
let mut gen = GeneratorA::start(); let mut gen = GeneratorA::start();
let mut gen2 = GeneratorA::start(); let mut gen2 = GeneratorA::start();
@@ -525,10 +527,14 @@ pub fn main() {
Wait? What happened to "Hello"? Wait? What happened to "Hello"?
Turns out that while the example above compiles Turns out that while the example above compiles just fine, we expose consumers
just fine, we expose consumers of this this API to both possible undefined of this this API to both possible undefined behavior and other memory errors
behavior and other memory errors while using just safe Rust. This is a big while using just safe Rust. This is a big problem!
problem!
> I've actually forced the code above to use the nightly version of the compiler.
> If you run [the example above on the playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=5cbe9897c0e23a502afd2740c7e78b98),
> you'll see that it runs without panic on the current stable (1.42.0) but
> panics on the current nightly (1.44.0). Scary!
We'll explain exactly what happened using a slightly simpler example in the next We'll explain exactly what happened using a slightly simpler example in the next
chapter and we'll fix our generator using `Pin` so join me as we explore chapter and we'll fix our generator using `Pin` so join me as we explore

View File

@@ -652,7 +652,7 @@ impl Generator for GeneratorA {
// the `String` earlier since these references will point to the // the `String` earlier since these references will point to the
// location in this stack frame which will not be valid anymore // location in this stack frame which will not be valid anymore
// when this function returns. // when this function returns.
if let GeneratorA::Yield1 {to_borrow, borrowed} = self { if let GeneratorA::Yield1 {to_borrow, borrowed} = this {
*borrowed = to_borrow; *borrowed = to_borrow;
} }