<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>Yosh Wuyts — Blog</title>
        <link>https://blog.yoshuawuyts.com</link>
        <description></description>
        <generator>Zola</generator>
        <language>en</language>
        <atom:link href="https://blog.yoshuawuyts.com/rss.xml" rel="self" type="application/rss+xml"/>
        <lastBuildDate>Thu, 05 Mar 2026 00:00:00 +0000</lastBuildDate>
        <item>
            <title>a grand vision for rust</title>
            <pubDate>Thu, 05 Mar 2026 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/a-grand-vision-for-rust/</link>
            <guid>https://blog.yoshuawuyts.com/a-grand-vision-for-rust/</guid>
            <description>&lt;p&gt;I don’t think I’ve ever quite articulated my “grand vision” for Rust, despite
having written a fair bit about the language and its features. There is a lot I
could say here, but currently there are three directions of development which I
find particularly interesting:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Improving Rust’s support for effects&lt;&#x2F;li&gt;
&lt;li&gt;Improving Rust’s support for substructural rules&lt;&#x2F;li&gt;
&lt;li&gt;Adding support for refinement types in Rust&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;There are more things in the language to be excited about, but these three in
particular interest me. If you’ve followed my work in Rust even a little bit for
the past few years, this might provide some clarity about what exactly it is I’m
trying to work towards here.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;effects&quot;&gt;Effects&lt;&#x2F;h2&gt;
&lt;p&gt;Rust has support for &lt;code&gt;const fn&lt;&#x2F;code&gt; and &lt;code&gt;async fn&lt;&#x2F;code&gt; on stable Rust. And on nightly it
also has support for &lt;code&gt;try fn&lt;&#x2F;code&gt; and &lt;code&gt;gen fn&lt;&#x2F;code&gt;. These are often referred to as
“function colors”, but more formally they’re also known as “effect types” which
are part of a broader category of programming language research called
“type-and-effect systems”.&lt;&#x2F;p&gt;
&lt;p&gt;Dealing with only one or two effects is generally &lt;em&gt;fine&lt;&#x2F;em&gt;. But the more effects
you add the more painful they become to work with. And from talking with people
who work on compilers, operating systems, VMs, and the like I believe that Rust
would benefit greatly from being able to provide more guarantees on functions
including:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Functions which guarantee they do not unwind (absence of  the &lt;code&gt;panic&lt;&#x2F;code&gt; effect)&lt;&#x2F;li&gt;
&lt;li&gt;Functions which guarantee they terminate (absence of the &lt;code&gt;div&lt;&#x2F;code&gt; effect)&lt;&#x2F;li&gt;
&lt;li&gt;Functions which are guaranteed to be deterministic  (absence of the &lt;code&gt;ndet&lt;&#x2F;code&gt; effect)&lt;&#x2F;li&gt;
&lt;li&gt;Functions which are guaranteed to not call host APIs (absence of the &lt;code&gt;io&lt;&#x2F;code&gt; effect)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That’s a lot of kinds of functions to introduce. But for the kinds of systems
that Rust wants to be used for all of these are &lt;em&gt;incredibly&lt;&#x2F;em&gt; useful. Which is
why I’m interested in adding the right abstractions that allow us to introduce
these kinds of functions in a way that feels good to use.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;substructural-types&quot;&gt;Substructural types&lt;&#x2F;h2&gt;
&lt;p&gt;Rust’s claim to fame is the introduction of the borrow checker, which statically
guarantees memory safety and without needing a garbage collector at runtime. In
formal terms, Rust’s type system is considered &lt;em&gt;affine&lt;&#x2F;em&gt;, which means that each
value must be used &lt;em&gt;at most once&lt;&#x2F;em&gt;. And “use at most once” is exactly what’s
needed to guarantee the absence of bugs like “use after free”.&lt;&#x2F;p&gt;
&lt;p&gt;But there are type systems which can provide even more guarantees. One step
beyond “use at most once” is “use exactly once”. Types that provide that guarantee
are called “linear” and in addition to guaranteeing the absence of “use after
free” they can also guarantee the absence of memory leaks.&lt;&#x2F;p&gt;
&lt;p&gt;And one step even beyond linear types are “ordered types”. These types aren’t
just used exactly once, they’re used exactly once in the exact order they were
introduced. What that means in practice: these are types with a stable memory
address that will never be changed until they are dropped. Here they are, side-by-side:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Type&lt;&#x2F;th&gt;&lt;th&gt;Usage&lt;&#x2F;th&gt;&lt;th&gt;Guarantees&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Affine types&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;at most once&lt;&#x2F;td&gt;&lt;td&gt;No more “use after free”&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Linear types&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;exactly once&lt;&#x2F;td&gt;&lt;td&gt;No more memory leaks&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Ordered types&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;exactly once, in-order&lt;&#x2F;td&gt;&lt;td&gt;Stable memory locations&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;I won’t bore you with terms like “contraction” and “weakening” here. You should
read &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Substructural_type_system&quot;&gt;the wikipedia
page&lt;&#x2F;a&gt; if you want to
learn more. But specifically for Rust: this is why we’ve been working on new
traits like &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;self-referential-types&#x2F;#immovable-types&quot;&gt;&lt;code&gt;Move&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;linear-types-one-pager&#x2F;&quot;&gt;&lt;code&gt;Forget&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;!Forget&lt;&#x2F;code&gt; unlocks linear types&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;!Move&lt;&#x2F;code&gt; unlocks ordered types &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#pin&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;pin&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Move unlocks ordered types in a way that &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;why-pin&#x2F;&quot;&gt;actually composes&lt;&#x2F;a&gt; with the rest of the language, unlike &lt;code&gt;Pin&lt;&#x2F;code&gt;. To be fully ergonomic does however also depend on &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;placing-functions&#x2F;&quot;&gt;emplacement in the language&lt;&#x2F;a&gt;, which I believe is best expressed as an effect.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;refinement-types&quot;&gt;Refinement types&lt;&#x2F;h2&gt;
&lt;p&gt;“Use after free” is more formally known as a &lt;em&gt;temporal memory safety violation&lt;&#x2F;em&gt;.
Its sibling is the “out of bounds error” which is also known as a &lt;em&gt;spatial
memory safety violation&lt;&#x2F;em&gt;
(&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;temporal-spatial-memory-safety&#x2F;&quot;&gt;ref&lt;&#x2F;a&gt;). In Rust
the borrow checker can entirely statically guarantee we never run into use after
free bugs. However if we want to relax those rules a little, we can opt-in to using types like &lt;code&gt;Rc&lt;&#x2F;code&gt; and &lt;code&gt;Arc&lt;&#x2F;code&gt; which check those properties at runtime instead.&lt;&#x2F;p&gt;
&lt;p&gt;When it comes to out of bounds checks things are however a little different. The
default is typically to check bounds at runtime, which may sometimes be omitted
by the compiler - but only as an optimization. That means we’re trading away
runtime performance for memory safety.&lt;&#x2F;p&gt;
&lt;p&gt;But what if we could trade away compile time for memory safety instead? Type
systems which can attach additional guarantees to existing types are called
&lt;em&gt;refinement type systems&lt;&#x2F;em&gt;. And for Rust we’re experimenting with an ultra-lightweight
version of this we’re calling &lt;em&gt;pattern types&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Pattern types use Rust’s pattern syntax to annotate existing types. Take for
example &lt;code&gt;NonZeroUsize&lt;&#x2F;code&gt;: this has historically been backed by a ton of custom
compiler optimizations to enable the use of niches in layout. But with pattern
types we can get those same optimizations automatically by &lt;em&gt;refinining&lt;&#x2F;em&gt; the
&lt;code&gt;usize&lt;&#x2F;code&gt; type with a pattern:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;NonZeroUsize = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt; is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;..;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                        ^^^^^^ refinement using patterns
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A closely related feature to pattern types are &lt;em&gt;view types&lt;&#x2F;em&gt;, which would enable the
compiler to consider disjoint patterns when reasoning about aliasing
(&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;syntactic-musings-on-view-types&#x2F;&quot;&gt;ref&lt;&#x2F;a&gt;). These
are great because they would allow holding two mutable references to the same
type, as long as each reference doesn’t look at any of the other fields.&lt;&#x2F;p&gt;
&lt;p&gt;I see pattern types and view types as the way we can make Rust’s borrow checker story &lt;em&gt;even better&lt;&#x2F;em&gt;. Both by removing the fundamental tradeoff between runtime checks vs memory safety (pattern types). As well as making even more valid borrows expressible (view types).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;There are a lot of things in Rust to be excited about. I love the work that’s
happening in improving the formalisms in the language, improvements in the
compiler, and in the ecosystem. And there are many more language improvements in
the works which I haven’t mentioned but I’m excited for (I’m looking at you,
reflection).&lt;&#x2F;p&gt;
&lt;p&gt;But me personally? I want for Rust to become the safest darn production-grade
language in existence. Because though we’re not doing too bad, we’re no
Ada&#x2F;SPARK yet. But also: working on features like these is what I find
interesting and exciting. It’s why I volunteer to work on Rust.&lt;&#x2F;p&gt;
&lt;p&gt;And while figuring out how to fundamentally improve Rust isn’t easy or quick. I
believe it is definitely possible, eventually worthwhile, and in my opinion:
a lot of fun!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Syntactic musings on the fallibility effect</title>
            <pubDate>Wed, 17 Dec 2025 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/syntactic-musings-on-the-fallibility-effect/</link>
            <guid>https://blog.yoshuawuyts.com/syntactic-musings-on-the-fallibility-effect/</guid>
            <description>&lt;p&gt;I believe it must have been about three or four years ago when Rust added the
unstable &lt;code&gt;yeet&lt;&#x2F;code&gt; keyword on nightly which can be used to return new errors in
&lt;code&gt;try&lt;&#x2F;code&gt;-functions. More recently Rust has added the unstable &lt;code&gt;bikeshed&lt;&#x2F;code&gt; keyword on
nightly which gives &lt;code&gt;try&lt;&#x2F;code&gt;-blocks and closures the ability to express which kind
of error they operate on. We’ve been deferring making decisions of error handling syntax for a while now, and I think that’s actually quite reasonable.&lt;&#x2F;p&gt;
&lt;p&gt;But if we want things to head for stable, we’re eventually going to want to
decide on syntax. And so I think it’s not a bad idea to start working through
the entire syntactic space here. And because things are unstable I guess it’s
unavoidable to also work through the semantic space here. I guess this is a
long-winded way of saying: in this post I’m sharing my opinions on Rust’s effect
for fallibility. And I’m doing that mostly because I think it’s fun to think about.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;defining-the-problem-space&quot;&gt;Defining the problem space&lt;&#x2F;h2&gt;
&lt;p&gt;For Rust we can categorize the error handling space into three categories. The first category are the places which carry the effect type notation, of which there are three. These are items in the language where for which we want to say: &lt;em&gt;“Hey, this right here is operating with an error handling context”&lt;&#x2F;em&gt;. Those items are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;blocks (&lt;code&gt;{}&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;functions (&lt;code&gt;fn f() {}&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;closures (&lt;code&gt;|| {}&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The second category are the effect operators. These are used inside of the items marked with the fallibility effect, and allow us to operate on them. There are three kinds of operations we need to support:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;create (e.g. &lt;code&gt;yield&lt;&#x2F;code&gt; for iteration)&lt;&#x2F;li&gt;
&lt;li&gt;propagate (e.g. &lt;code&gt;.await&lt;&#x2F;code&gt; for async)&lt;&#x2F;li&gt;
&lt;li&gt;consume (e.g. &lt;code&gt;block_on&lt;&#x2F;code&gt; for async, &lt;code&gt;for..in&lt;&#x2F;code&gt; for iteration)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Both of the categories we’ve seen so far apply to all of Rust’s control-flow effects (async, fallibility, and iteration). But the third category is unique to fallibility only, and that is: specialization. Fallibility has two modes it can operate in:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;abstract, where the effect is reified into an abstract &lt;code&gt;-&amp;gt; impl Try&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;concrete, where the effect is reified into a specific type (e.g. &lt;code&gt;-&amp;gt; io::Result&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You can almost think of fallibility as being two separate effects in a trenchcoat. Or maybe as “concrete” being a specialized version of “abstract”. But since both flavors of fallibility are so similar in both purpose and usage, to an end-user we will both to feel similar to one another.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fallible-functions&quot;&gt;Fallible functions&lt;&#x2F;h2&gt;
&lt;p&gt;So for the effect type we have to account for functions, closures, and blocks.
For both of these we need to be able to support both abstract and concrete
variants. Or put differently: we need to be able to optionally be able spell out
both the explicit type when needed.&lt;&#x2F;p&gt;
&lt;p&gt;Starting with functions. Swift uses the &lt;code&gt;throws&lt;&#x2F;code&gt; keyword to annotate a function as fallible. I believe this matches Java, Kotlin, and Scala. This keyword can optionally carry a concrete type, and I think that’s perfect. Here is how I would adapt that for Rust:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() {}                       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `-&amp;gt; ()` (base)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() throws {}                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `-&amp;gt; impl Try`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() throws Err(io::Error) {} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `-&amp;gt; io::Result&amp;lt;()&amp;gt;`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() throws None {}           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `-&amp;gt; Option&amp;lt;()&amp;gt;`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() throws None -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32 &lt;&#x2F;span&gt;&lt;span&gt;{}    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `-&amp;gt; Option&amp;lt;i32&amp;gt;`
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The notation here borrows from pattern types. &lt;code&gt;None&lt;&#x2F;code&gt; and &lt;code&gt;Err&lt;&#x2F;code&gt; imported as part of the Rust prelude, and just like we can write &lt;code&gt;None&lt;&#x2F;code&gt; and &lt;code&gt;Err&lt;&#x2F;code&gt; are in function bodies, we should be able to use them freely in signatures as well. And since we know they are part of an &lt;code&gt;impl Try&lt;&#x2F;code&gt;, we know what the actual type is. The only open question I have is express that in the &lt;code&gt;impl Try&lt;&#x2F;code&gt; trait itself - but the &lt;code&gt;Try&lt;&#x2F;code&gt; trait is still unstable, so that’s something we can figure out.&lt;&#x2F;p&gt;
&lt;p&gt;In terms of location this follows what Swift does, listing effects after the argument list but before the arrow. This to me makes sense because effects describe properties of the function itself. And because &lt;code&gt;throws&lt;&#x2F;code&gt; says something about the function’s outputs, I expect it to be listed &lt;em&gt;after&lt;&#x2F;em&gt; the argument list. And because we don’t want it to be confused with the logical return type, it makes sense for it to be listed &lt;em&gt;before&lt;&#x2F;em&gt; the return type.&lt;&#x2F;p&gt;
&lt;p&gt;Something to be aware of also is that it’s notationally important that we are
always able strip the effect from the function signature and still end up with a
valid function signature. That’s an important property we need to be able to
group effects together and reason about them in sets or as variables. Those
include things like: effect aliases, associated effects, and effect generics:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Adding or removing effects from functions should
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; not affect the rest of the function signature:
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;;       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; async effect
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;;       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; const effect
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() throws None -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; fallible effect
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;;             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; no effects (baseline)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; That keeps the door open to enable higher-order reasoning
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; about effects. Using a Flix-inspired notation for fun:
&lt;&#x2F;span&gt;&lt;span&gt;effect ef = async + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span&gt;+ throws None;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32 &lt;&#x2F;span&gt;&lt;span&gt;\ ef;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Maybe there’s something to be said for going all the way with our notation
and start the migration to a general-purpose effect notation. But I’m somewhat intentionally trying to scope things down here and argue for more localized decisions on how we notate fallibility. But I can be convinced to do something more generic&#x2F;consistent if people feel strongly we should do it all in one go.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fallible-blocks-and-closures&quot;&gt;Fallible blocks and closures&lt;&#x2F;h2&gt;
&lt;p&gt;Blocks and closures are very similar in how they’re written; with the exception that closures must list their arguments and may list their return type. I think our block notation is a little goofy overall, and wish it would be able to list return types too. In my opinion Swift does this better in their &lt;code&gt;do&lt;&#x2F;code&gt; statements, and like I kind of wish we would have that for blocks. But we don’t do that right now, so I think we should start by spelling closures and blocks as follows:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; abstract definitions
&lt;&#x2F;span&gt;&lt;span&gt;throws {}            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; block notation
&lt;&#x2F;span&gt;&lt;span&gt;throws || {}         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; closure notation
&lt;&#x2F;span&gt;&lt;span&gt;throws || -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32 &lt;&#x2F;span&gt;&lt;span&gt;{}  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; explicit return type
&lt;&#x2F;span&gt;&lt;span&gt;async throws || {}   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; mixing effects
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; concrete definitions
&lt;&#x2F;span&gt;&lt;span&gt;throws None {}           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; block notation
&lt;&#x2F;span&gt;&lt;span&gt;throws None || {}        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; closure notation
&lt;&#x2F;span&gt;&lt;span&gt;throws None || -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32 &lt;&#x2F;span&gt;&lt;span&gt;{} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; explicit return type
&lt;&#x2F;span&gt;&lt;span&gt;async throws None || {}  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; mixing effects
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Personally I don’t love that the effects are listed here &lt;em&gt;before&lt;&#x2F;em&gt; the argument list, while in &lt;code&gt;fn() {}&lt;&#x2F;code&gt;-functions the effects are listed &lt;em&gt;after&lt;&#x2F;em&gt; the argument list (and before the arrow). And so it’s weird to me if closures don’t follow this same syntactic pattern. But I think making that more consistent is something we can probably address later.&lt;&#x2F;p&gt;
&lt;p&gt;What probably stands out here though is that I’m opting to fully omit the &lt;code&gt;try&lt;&#x2F;code&gt; keyword. The way I see it there are three options for how can we spell things here:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;try {}&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;try throws None {}&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;try throws {}&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;try throws None {}&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;throws {}&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;throws None {}&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Personally I prefer the last one, omitting the &lt;code&gt;try&lt;&#x2F;code&gt; keyword entirely. Though I like &lt;code&gt;try&lt;&#x2F;code&gt; as a verb, it doesn’t carry any additional information that &lt;code&gt;throws&lt;&#x2F;code&gt; doesn’t already. And so I remind myself of &lt;a href=&quot;https:&#x2F;&#x2F;buttondown.com&#x2F;hillelwayne&#x2F;archive&#x2F;stroustrups-rule&#x2F;&quot;&gt;Stroustrup’s Rule&lt;&#x2F;a&gt; and away &lt;code&gt;try&lt;&#x2F;code&gt; goes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;operating-on-fallibility&quot;&gt;Operating on fallibility&lt;&#x2F;h2&gt;
&lt;p&gt;There are three kinds of operations we need to support for fallibility: create,
propagate, and consume. The latter of the two we already have in the language, so let’s start there. To “forward” the fallibility effect in code, you can use what is officially called &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;reference&#x2F;expressions&#x2F;operator-expr.html?highlight=question%20mark#the-try-propagation-expression&quot;&gt;“the try propagation expression”&lt;&#x2F;a&gt; - though it is more commonly known as “the question mark operator”:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;()?; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `?` propagates the fallibility effect
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Try propagation expressions can only be used in functions which themselves return an &lt;code&gt;impl Try&lt;&#x2F;code&gt; (either abstract or concrete). If we have a function which itself is infallible, or has a different &lt;code&gt;Try&lt;&#x2F;code&gt; type, we will want to &lt;em&gt;consume&lt;&#x2F;em&gt; the fallible effect. To do that we can use the &lt;code&gt;match&lt;&#x2F;code&gt; keyword. If we are working with an abstract &lt;code&gt;impl Try&lt;&#x2F;code&gt; implementation we will first need to cast it to a concrete type. But otherwise the logic is the same for both:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `match` consumes a concrete `Result` type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(x) =&amp;gt; { .. }
&lt;&#x2F;span&gt;&lt;span&gt;    Err(err) =&amp;gt; { .. }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `match` consumes an abstract `impl Try` type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; NOTE: this should probably become a combinator on `Try`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;branch&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    Break(b) =&amp;gt; FromResidual::from_residual(b), 
&lt;&#x2F;span&gt;&lt;span&gt;    Continue(c) =&amp;gt; Try::from_output(c),
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; res {
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(x) =&amp;gt; { .. }
&lt;&#x2F;span&gt;&lt;span&gt;    Err(err) =&amp;gt; { .. }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then finally we have the missing “create” operator which allows you to create a new &lt;code&gt;impl Try&lt;&#x2F;code&gt; type. On unstable today this is called &lt;code&gt;yeet&lt;&#x2F;code&gt;, and though I think the name is funny, I think it should probably be called &lt;code&gt;throw&lt;&#x2F;code&gt;. Here is how you would use it inside of functions:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;throw None;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; -&amp;gt; `return None`
&lt;&#x2F;span&gt;&lt;span&gt;throw Err(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; -&amp;gt; `return Err(&amp;quot;hello&amp;quot;.into())`
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And that is all three control-flow operations accounted for: &lt;code&gt;?&lt;&#x2F;code&gt;, &lt;code&gt;match&lt;&#x2F;code&gt;, and &lt;code&gt;throw&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;notes-on-effect-naming&quot;&gt;Notes on effect naming&lt;&#x2F;h2&gt;
&lt;p&gt;Though I like the &lt;code&gt;throw&lt;&#x2F;code&gt; terminology overall, I think it could do with some tidying up. If we’re going to go with &lt;code&gt;throw&lt;&#x2F;code&gt;, I want us to &lt;em&gt;really&lt;&#x2F;em&gt; lean into it. To me using &lt;code&gt;try&lt;&#x2F;code&gt; as a noun feels really unintuitive, and so I’d much rather we use nouns and verbs based on the &lt;code&gt;throw&lt;&#x2F;code&gt; operation instead:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Try&lt;&#x2F;code&gt; → &lt;code&gt;Throwable&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;try&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;try..bikeshed&lt;&#x2F;code&gt; → &lt;code&gt;throws&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;yeet&lt;&#x2F;code&gt; → &lt;code&gt;throw&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;?&lt;&#x2F;code&gt; (try propagation operator) → &lt;code&gt;?&lt;&#x2F;code&gt; (rethrow operator)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;To me this degree of regularity is incredibly appealing. Aside from the general-purpose &lt;code&gt;match&lt;&#x2F;code&gt; operation, all of these items seem clearly related to each other. And I think that’s really valuable! In a previous post I made a similar case for the iteration effect as well. Here is what I would change if I could (though I’m not saying we should):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;IntoIterator&lt;&#x2F;code&gt; → &lt;code&gt;Iterate&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;FromIterator&lt;&#x2F;code&gt; → &lt;code&gt;Collect&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;Iterate&lt;&#x2F;em&gt; is the name of the operation, which itself returns an &lt;em&gt;iterator&lt;&#x2F;em&gt; which can be iterated over. The async effect could probably also do with some normalization, since we’re currently mixing the terms “async”, “future”, and “poll” in ways that take time to internalize. I think some normalization of terminology here could be nice too (I’m musing, not prescribing):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;IntoFuture&lt;&#x2F;code&gt; → &lt;code&gt;Wait&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Future&lt;&#x2F;code&gt; → &lt;code&gt;Waitable&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Future::poll&lt;&#x2F;code&gt; → &lt;code&gt;Waitable::wait&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Poll&lt;&#x2F;code&gt; → &lt;code&gt;WaitableState&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I guess though if we had a “throwable” and a “waitable”, then we might also want
an “iterable”. I do like “iterable” less than “iterator”, but personally I like
consistency even more. Though in the grand scheme of things: this specific name doesn’t matter too much either.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;motivating-reification-into-an-abstract-type&quot;&gt;Motivating reification into an abstract type&lt;&#x2F;h2&gt;
&lt;p&gt;I didn’t really get into it before in this post, but I think we’re currently underestimating just how valuable it is for functions to be able to choose whether they are able to return an abstract &lt;code&gt;impl Try&lt;&#x2F;code&gt; or a concrete &lt;code&gt;Try&lt;&#x2F;code&gt; type. In my &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;error-handling-survey&#x2F;#auto-enums&quot;&gt;2019 error handling survey&lt;&#x2F;a&gt; I highlighted the auto-enums crate which is able to automatically enable heterogenous types to be returned from function bodies.&lt;&#x2F;p&gt;
&lt;p&gt;I see this combination of features becoming the language-native way to provide
80% of the value of the &lt;code&gt;anyhow::Error&lt;&#x2F;code&gt; type. Instead of casting error types to a &lt;code&gt;Box&amp;lt;dyn Error + Send + Sync + &#x27;static&amp;gt;&lt;&#x2F;code&gt;, this would cast the error to an anonymous &lt;code&gt;enum Error {}&lt;&#x2F;code&gt; with a variant per-type. That means:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;no allocations are involved&lt;&#x2F;li&gt;
&lt;li&gt;each error variant is explicitly tracked&lt;&#x2F;li&gt;
&lt;li&gt;syntactically easy to write&lt;&#x2F;li&gt;
&lt;li&gt;natural upgrade path to explicit error types (e.g. &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;thiserror&#x2F;latest&#x2F;thiserror&#x2F;&quot;&gt;thiserror&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Here is an example of how I see that playing out. Function &lt;code&gt;bar&lt;&#x2F;code&gt; here can either
&lt;code&gt;throw i32&lt;&#x2F;code&gt; or &lt;code&gt;throw &amp;amp;&#x27;static str&lt;&#x2F;code&gt;. The idea is that the compiler would recognize this, create an anonymous enum that can hold both types, and then return that as the error type:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt;) throws {  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `throws i32 | &amp;amp;&amp;#39;static str`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span&gt;(x)?;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt;) throws {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; x {
&lt;&#x2F;span&gt;&lt;span&gt;       throw &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `: i32`
&lt;&#x2F;span&gt;&lt;span&gt;    } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;       throw &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;oops&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `: &amp;amp;&amp;#39;static str`
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The exact rules of how this would work would be a little subtle. We likely
wouldn’t be able to just to coerce errors using &lt;code&gt;.into()&lt;&#x2F;code&gt; the way we do today. But I think in the short term, we could get away with some basic rules to hold space for this in the future. So bare &lt;code&gt;fn() throws {}&lt;&#x2F;code&gt; functions:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Should return an abstract &lt;code&gt;impl Try&lt;&#x2F;code&gt; type&lt;&#x2F;li&gt;
&lt;li&gt;Should not call &lt;code&gt;.into&lt;&#x2F;code&gt; as part of the &lt;code&gt;?&lt;&#x2F;code&gt; desugaring to coerce types&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And I believe that’s about it. But I’m keen to hear from Scott (T-Lang) to tell me exactly what I’ve missed and why this might not be enough.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;closing-words&quot;&gt;Closing words&lt;&#x2F;h2&gt;
&lt;p&gt;And that’s a complete design for a fallibility effect notation done. I know not everyone will like &lt;code&gt;throw&lt;&#x2F;code&gt; as much as I do, but my hope is to steer any discussion here at least to some regularity. Say if we want to go with &lt;code&gt;yeet&lt;&#x2F;code&gt;, I believe the right terminology should then become &lt;code&gt;yeets&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;Yeetable&lt;&#x2F;code&gt;&#x2F;”re-yeet”. Personally I tend to care more about the system and framework we apply, than about the exact keyword we end up using.&lt;&#x2F;p&gt;
&lt;p&gt;Something that’s stood out while writing this is that the fallibility effect doesn’t seem to have a moral equivalent to &lt;code&gt;IntoIterator&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;IntoFuture&lt;&#x2F;code&gt; right now. I guess we have the automatic &lt;code&gt;Into&lt;&#x2F;code&gt; conversion that is applied when we use &lt;code&gt;?&lt;&#x2F;code&gt;. But that is more general-purpose, and I’m having some trouble working through the exact implications of not having a separate trait.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, that’s it. I had a lot of fun writing this, and I hope it makes for an interesting read. Happy December!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Placing Arguments</title>
            <pubDate>Wed, 13 Aug 2025 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/placing-arguments/</link>
            <guid>https://blog.yoshuawuyts.com/placing-arguments/</guid>
            <description>&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;In my last post I introduced &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;placing-functions&#x2F;&quot;&gt;placing
functions&lt;&#x2F;a&gt;, which are functions
that can “return” values without copying them. This is useful not just because
it’s more efficient (fewer copies), but also because it guarantees addresses
remain stable - which is something we need for types that have internal borrows
(self-referential types). Here is a little reminder of what placing functions look like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;placing&lt;&#x2F;span&gt;&lt;span&gt;]                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← 1. Marks a function as &amp;quot;placing&amp;quot;.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new_cat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Cat {  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← 2. Has a logical return type of `Cat`.
&lt;&#x2F;span&gt;&lt;span&gt;    Cat { age }               &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← 3. Constructs `Cat` in the caller&amp;#39;s frame.
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see this is just regular Rust code, with the only difference being
the added &lt;code&gt;#[placing]&lt;&#x2F;code&gt; (placeholder) notation. The main idea behind placing
functions is &lt;em&gt;backwards-compatibility&lt;&#x2F;em&gt;, meaning: we should be able to
progressively add &lt;code&gt;#[placing]&lt;&#x2F;code&gt; notations to the entire stdlib, just like we’re
doing with const. Which is important, because we don’t want to add yet another
axis to the language, locking out address-sensitive types from being used with
existing traits and functions. We’re already suffering through &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;why-pin&#x2F;&quot;&gt;the bifurcation
&lt;code&gt;Pin&lt;&#x2F;code&gt; has introduced&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, and I don’t
think we should go through this again for self-referential types.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;And no, unfortunately the “pin ergonomics” experiment won’t do anything to resolve this problem. I think it’s a shame we’re not taking this problem more seriously, because this kind of incompatibility affects the language in ways that extend far beyond syntax and conveniences.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;placing-functions&quot;&gt;Placing Functions&lt;&#x2F;h2&gt;
&lt;p&gt;It’s cool to have ideals and visions for how thing should be, but we do always
need to square that with reality. And while &lt;em&gt;placing functions&lt;&#x2F;em&gt; seem like they
will work without a hitch (fallible placing functions post tbd), it’s &lt;em&gt;placing
arguments&lt;&#x2F;em&gt; which seem like they’re going to be a problem. To recap what placing
arguments are about, the idea is that we would be able to write the following
definition, and things would &lt;em&gt;just work&lt;&#x2F;em&gt; without any copies:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; Box&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `Box::new` here takes type `T` and
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; constructs it in-place on the heap
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;: #[placing] T) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ ... }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In the post I made the following assertion (in bold even, because it’s important):&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;As a core design constraint: invoking a function that takes placing arguments should be no different from a regular function. This is needed to keep APIs backwards-compatible.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Cool idea, just one small hitch: we can’t actually do that. And that is because
&lt;em&gt;placing arguments&lt;&#x2F;em&gt; fundamentally encode &lt;em&gt;callback semantics&lt;&#x2F;em&gt;. Olivier Faure
provided this example to prove why:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x = Box::new({
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To preserve compatibility, we need to preserve order of execution. In Rust today
if you call this, the expression in &lt;code&gt;Box::new&lt;&#x2F;code&gt; will be evaluated before
&lt;code&gt;Box::new&lt;&#x2F;code&gt; is called. In this case that means that this will return before
&lt;code&gt;Box::new&lt;&#x2F;code&gt; has a chance to allocate.&lt;&#x2F;p&gt;
&lt;p&gt;If we applied placing semantics, it would fundamentally need to change the
ordering. Before we can place, the place has to be created. In this case that
place is on the heap, which means interacting with the allocator, which in Rust
can panic. That means that code which looks like it should &lt;code&gt;return&lt;&#x2F;code&gt; before it
calls the function, would actually panic. And that’s bad!&lt;&#x2F;p&gt;
&lt;p&gt;To fully push this point home, Taylor Cramer recently provided an example which
showed how the execution ordering also causes issues with the borrow checker. In this example we would need to hold &lt;code&gt;&amp;amp;vec&lt;&#x2F;code&gt; as part of the expression for &lt;code&gt;vec.len&lt;&#x2F;code&gt;, while also holding &lt;code&gt;&amp;amp;mut vec&lt;&#x2F;code&gt; for &lt;code&gt;vec.push&lt;&#x2F;code&gt;. And that can’t work; not even with &lt;a href=&quot;https:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2025&#x2F;02&#x2F;25&#x2F;view-types-redux&#x2F;&quot;&gt;view types and abstract fields&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#len&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;len&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Both &lt;code&gt;Vec::len&lt;&#x2F;code&gt; and &lt;code&gt;Vec::push&lt;&#x2F;code&gt; need to access the vector’s “length”. Virtualizing fields &#x2F; partial borrows won’t change that.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;   vec.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;make_big_thing&lt;&#x2F;span&gt;&lt;span&gt;(vec.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;()));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ^^^^^^^^                ^^^^^^^
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; | &amp;amp;mut vec              | &amp;amp;vec
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;closures&quot;&gt;Closures&lt;&#x2F;h2&gt;
&lt;p&gt;The only way I see us making sense of this is by actually requiring that users
use closures here. That would make the ordering far clearer, and preventing any
surprises about ordering or borrows. Ralf Jung made the observation that
&lt;code&gt;FnOnce&lt;&#x2F;code&gt; for these kinds of scenarios actually perfectly encodes the semantics
we want, and I agree. Consider this example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;vec.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(|| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;make_big_thing&lt;&#x2F;span&gt;&lt;span&gt;(vec.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;()));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This would give the following error:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;error[E0502]: cannot borrow `vec` as mutable because it is also borrowed as immutable
&lt;&#x2F;span&gt;&lt;span&gt;  --&amp;gt; src&#x2F;main.rs:50:9
&lt;&#x2F;span&gt;&lt;span&gt;   |
&lt;&#x2F;span&gt;&lt;span&gt;47 |   vec.push(|| make_big_thing(vec.len()));
&lt;&#x2F;span&gt;&lt;span&gt;   |                              --- immutable borrow occurs here
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;47 |   vec.push(|| make_big_thing(vec.len()));
&lt;&#x2F;span&gt;&lt;span&gt;   |   ^^^ mutable borrow occurs here
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There is nothing specific to placing functions about this error, just like
there’s nothing special about solving it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; len = vec.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;vec.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(|| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;make_big_thing&lt;&#x2F;span&gt;&lt;span&gt;(len));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But we can’t just change the signature of &lt;code&gt;Vec::push&lt;&#x2F;code&gt; to take closures. Instead
we would need to introduce a new method, e.g. &lt;code&gt;Vec::push_with&lt;&#x2F;code&gt; that can take a
closure and place its outputs:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; Vec&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;push_with&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;F&amp;gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;: F)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;        F: #[placing] FnOnce() -&amp;gt; T;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And this points us to a rather important challenge with these APIs, because for
all intents and purposes this sets us down the path of deprecating &lt;code&gt;Vec::push&lt;&#x2F;code&gt;.
The &lt;code&gt;Vec::push_with&lt;&#x2F;code&gt; method is more efficient than &lt;code&gt;Vec::push&lt;&#x2F;code&gt;, and beyond some
compat reasons there will be no reason to keep using &lt;code&gt;Vec::push&lt;&#x2F;code&gt;. So people will
naturally begin treating &lt;code&gt;Vec::push&lt;&#x2F;code&gt; as legacy, even if we don’t outright mark
it as such.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;edition-dependent-path-resolution&quot;&gt;Edition-dependent path resolution&lt;&#x2F;h2&gt;
&lt;p&gt;I’m a firm believer that the obvious choice for something should be the right
choice &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. It feels bad to scold people for using &lt;code&gt;Box::new&lt;&#x2F;code&gt;, telling the that they
should be using &lt;code&gt;Box::new_with&lt;&#x2F;code&gt; instead. Or instead of calling
&lt;code&gt;Hashmap::insert&lt;&#x2F;code&gt;, they should be calling &lt;code&gt;Hashmap::insert_with&lt;&#x2F;code&gt;. And so on.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;While not quite the same, you can see this same idea of “the default way should be the right way” reflected in the safety practice of &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Poka-yoke&quot;&gt;poka-yoke&lt;&#x2F;a&gt;. Or in Hollnagel’s distinction between &lt;a href=&quot;https:&#x2F;&#x2F;erikhollnagel.com&#x2F;ideas&#x2F;safety-i%20and%20safety-ii.html&quot;&gt;Safety 1 and Safety 2&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;My preferred way of resolving this would be to have a notion of
&lt;em&gt;edition-dependent paths&lt;&#x2F;em&gt;: imports and symbols that resolve differently
depending on which edition you’re compiling on. For example on edition &lt;code&gt;2024&lt;&#x2F;code&gt;
and below, people would see both &lt;code&gt;Vec::push&lt;&#x2F;code&gt; and &lt;code&gt;Vec::push_with&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; Vec&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;item&lt;&#x2F;span&gt;&lt;span&gt;: T);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;push_with&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;: impl #[placing] FnOnce() -&amp;gt; T);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But on edition &lt;code&gt;2024 + 1&lt;&#x2F;code&gt; we would be able to deprecate &lt;code&gt;Vec::push&lt;&#x2F;code&gt; and rename it to
something else (e.g. &lt;code&gt;push_without&lt;&#x2F;code&gt;), and have &lt;code&gt;Vec::push_with&lt;&#x2F;code&gt; take its place:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; Vec&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Is called `push_with` on editions 2024 and below
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;: impl #[placing] FnOnce() -&amp;gt; T);
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Is called `push` on editions 2024 and below
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;deprecated&lt;&#x2F;span&gt;&lt;span&gt;(note = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;please use `push` instead&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;push_without&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;item&lt;&#x2F;span&gt;&lt;span&gt;: T);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Under the hood these functions would still resolve to the same symbols after
accounting for editions. Conceptually what this needs is a stable,
edition-independent identifier that libraries can map back onto in
edition-specific ways:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;stable identifier&lt;&#x2F;th&gt;&lt;th&gt;edition 2024&lt;&#x2F;th&gt;&lt;th&gt;edition 2024 + 1&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;::std::vec::Vec::push&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Vec::push&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Vec::push_without&lt;&#x2F;code&gt; †&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;::std::vec::Vec::push_with&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Vec::push_with&lt;&#x2F;code&gt; †&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Vec::push&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;em&gt;†: These names are for illustrative purposes only; they are not concrete proposals.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;And we could even go further with this, where in a hypothetical edition &lt;code&gt;2024 + 2&lt;&#x2F;code&gt; we might remove the old API entirely, so you would only ever be able to use the new API:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; Vec&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Is called `push_with` on editions 2024 and below;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `push_without` is no longer available.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;: impl #[placing] FnOnce() -&amp;gt; T);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The main reason why we don’t have a system like this already is because it would
be a lot of work and there are guaranteed to be edge cases that make this harder
than you’d assume it is. The basic design I’m describing here is something
people have thought of before, and that’s not the reason it hasn’t happened yet.&lt;&#x2F;p&gt;
&lt;p&gt;However useful edition-dependent path resolution would be in the long run, we
don’t need it out of the gate. We can begin by adding placing variants of
existing methods to the stdlib. It’s probably enough to proceed with, knowing edition-dependent path resolution might be possible in the future.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Alice Ryhl for reviewing this post.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>placing functions</title>
            <pubDate>Tue, 08 Jul 2025 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/placing-functions/</link>
            <guid>https://blog.yoshuawuyts.com/placing-functions/</guid>
            <description>&lt;h2 id=&quot;what-are-placing-functions&quot;&gt;What are placing functions?&lt;&#x2F;h2&gt;
&lt;p&gt;About a year ago I observed that &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;in-place-construction-seems-surprisingly-simple&#x2F;&quot;&gt;in-place construction seems surprisingly
simple&lt;&#x2F;a&gt;.
By separating the creating of the place in memory from writing the value to
memory, it’s not that hard to see how we can turn that into a language feature.
So about six months ago, that’s what I went ahead and did and created the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yoshuawuyts&#x2F;placing&quot;&gt;placing crate&lt;&#x2F;a&gt;: a proc-macro-based prototype for “placing functions”.&lt;&#x2F;p&gt;
&lt;p&gt;Placing functions are functions whose return type is constructed in the caller’s
stack frame rather than in the function’s stack frame. This means that the
address from the moment on construction is &lt;em&gt;stable&lt;&#x2F;em&gt;. Which may not only lead to
improved performance, it also serves as the foundation for a number of
useful features like supporting &lt;code&gt;dyn&lt;&#x2F;code&gt; AFITs (Async Functions in Traits) &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In this post I’ll be explaining how placing functions desugar, why placing
functions are the right solution for emplacement, and how placing functions
integrate into the language. Not in as much detail as I’d do for an actual RFC,
but more as a broad introduction to the &lt;em&gt;idea&lt;&#x2F;em&gt; of placing functions. And to get
right into it, here is a basic example of how this would work:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;placing&lt;&#x2F;span&gt;&lt;span&gt;]       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Marks a function as &amp;quot;placing&amp;quot;.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ age } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Constructs `Self` in the caller&amp;#39;s frame.
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.age
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cat = Cat::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `Cat` is constructed in-place.
&lt;&#x2F;span&gt;&lt;span&gt;    assert_eq!(cat.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;(), &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;a-basic-desugaring&quot;&gt;A basic desugaring&lt;&#x2F;h2&gt;
&lt;p&gt;The purpose of the &lt;code&gt;placing&lt;&#x2F;code&gt; crate is to prove that placing functions should not
be that hard to implement. I managed to implement a working prototype in a few hours over my winter holidays. In total I&#x27;ve spent maybe four or so days on the implementation. I’m not a compiler engineer though, and I expect that the lovely folks on
T-Compiler can probably recreate this in a fraction of the time it took me.&lt;&#x2F;p&gt;
&lt;p&gt;Since I don&#x27;t know my way around the rustc frontend, I implemented the placing crate entirely using proc macros. The upside was that I could get something working more quickly. The downside is that proc macros don’t have access to type information, so I had to hack around that limitation. Which results in an API that requires a lot of proc macro attributes. But that’s ok for a proof of concept.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s walk through the basic example I
showed earlier, but this time using the proc macros. Starting by installing the
placing crate:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; cargo add placing
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can then import &lt;code&gt;placing&lt;&#x2F;code&gt; and define our main struct &lt;code&gt;Cat&lt;&#x2F;code&gt;. We need to
annotate this with the &lt;code&gt;#[placing]&lt;&#x2F;code&gt; attribute macro because we need to change
the internal representation slightly. Here is what this looks like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Original
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;placing::placing;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;placing&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let’s take a look at what the &lt;code&gt;#[placing]&lt;&#x2F;code&gt; annotation expands to. As I said in
the intro: placing functions separate the creation of the memory location from
the initialization of the values in said location. For our type &lt;code&gt;Cat&lt;&#x2F;code&gt;, the
location must be of type &lt;code&gt;MaybeUninit&amp;lt;Cat&amp;gt;&lt;&#x2F;code&gt;. But because we want to keep the
type the same, even if we change how the internals work, we actually want to
keep &lt;code&gt;Cat&lt;&#x2F;code&gt; as the outer type name and move the fields into an internal
&lt;code&gt;MaybeUninit&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Desugared
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::mem::MaybeUninit;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; This keeps the same external type,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; but changes the internals to store the fields
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; in a `MaybeUninit`.
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;repr&lt;&#x2F;span&gt;&lt;span&gt;(transparent)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Cat(MaybeUninit&amp;lt;InnerCat&amp;gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; These are the fields contained in the original
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; type `Cat`. But separated so that they can be
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; wrapped in a `MaybeUninit` internally.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;InnerCat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Our desugaring needs to add one last bit to our type definition to ensure it works correctly.
Because we are now holding a &lt;code&gt;MaybeUninit&lt;&#x2F;code&gt; we have to make sure it calls its
destructors when dropped. This means our desugaring  needs to generate a &lt;code&gt;Drop&lt;&#x2F;code&gt; implementation
that calls through the &lt;code&gt;MaybeUninit&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Desugared
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Drop &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The constructors guarantee this will never
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; be dropped before it has been initialized.
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;assume_init_drop&lt;&#x2F;span&gt;&lt;span&gt;() }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now that we have our type definition, let’s show how to implement the &lt;code&gt;new&lt;&#x2F;code&gt;
constructor. Because we don’t have access to type information the placing crate
requires annotations on both the impl block and the method:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Original
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;placing&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;placing&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ age }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the trickiest part of the desugaring because it needs to split up the
constructor into two parts. One to create the place, the other to initialize the
values in-place. Conceptually that means rewriting the return type of the last
line into writing into a mutable argument instead.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Desugared
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::mem::MaybeUninit;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Calling this function constructs the place to
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; initialize the type into. This is part of a
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; two-part constructor, and it must always be
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; followed by a call to `new_init`.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new_uninit&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;(MaybeUninit::uninit())
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; This initializes the values of the type in-place.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; `new_init` must not be called more than once, and
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; must always follow a call to `new_uninit`.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new_init&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; this = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut_ptr&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ (&amp;amp;raw &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;(*this).age).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(age) };
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next we also have a getter function. All we need to do with that is teach it how
to reach through the outer struct and into the inner fields. Here is the
definition:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Original
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;placing&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.age
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And here is what it expands to:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Desugared
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; this = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;assume_init_ref&lt;&#x2F;span&gt;&lt;span&gt;() };
&lt;&#x2F;span&gt;&lt;span&gt;        this.age
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With that we’re now ready to create an instance of &lt;code&gt;Cat&lt;&#x2F;code&gt; in-place, and invoke
our getter. This is the only part that can’t be abstracted away, since Rust
macros have very strict scoping rules compared to if we implemented this
directly in the compiler. What we really wish we could do would be this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cat = placing!(Cat, new, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But for now we have to call this manually instead, and so the invocation looks
like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Original
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; cat = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Cat::new_uninit() };
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ cat.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;new_init&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;) };
&lt;&#x2F;span&gt;&lt;span&gt;    assert_eq!(cat.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;(), &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As an aside: in Rust we now have the experimental &lt;code&gt;super_let&lt;&#x2F;code&gt; feature which
makes it possible to construct types in the enclosing scope, but reference them
afterwards. This &lt;em&gt;almost&lt;&#x2F;em&gt; works for our use case, except it can only return
references, not owned types. That means the best we can do with that feature is the following (&lt;a href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=nightly&amp;amp;mode=debug&amp;amp;edition=2024&amp;amp;gist=606a4613c99f3a76c189537c92b9e116&quot;&gt;playground&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;feature&lt;&#x2F;span&gt;&lt;span&gt;(super_let)]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;macro_rules! &lt;&#x2F;span&gt;&lt;span&gt;new_cat {
&lt;&#x2F;span&gt;&lt;span&gt;    (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$value&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;expr &lt;&#x2F;span&gt;&lt;span&gt;$(,)?) =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;super let mut&lt;&#x2F;span&gt;&lt;span&gt; cat = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Cat::new_uninit()) };
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Cat::new_init(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; cat, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$value&lt;&#x2F;span&gt;&lt;span&gt;) };
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; cat &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← ❌ Returns by-ref rather than by-value
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we try and return an owned value it actually copies it - which is exactly
what we’re trying to avoid. We might be able to change that in the compiler
implementation. And to summarize: here is the &lt;code&gt;placing&lt;&#x2F;code&gt; crate’s version of our original example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Original
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;placing::placing;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;placing&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;placing&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;placing&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ age }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.age
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `Cat` is constructed in-place.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; cat = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Cat::new_uninit() };
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ cat.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;new_init&lt;&#x2F;span&gt;&lt;span&gt;() };
&lt;&#x2F;span&gt;&lt;span&gt; 
&lt;&#x2F;span&gt;&lt;span&gt;    assert_eq!(cat.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;(), &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And here is the same code with all the macros expanded:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Desugared
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::mem::MaybeUninit;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;repr&lt;&#x2F;span&gt;&lt;span&gt;(transparent)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat(MaybeUninit&amp;lt;InnerCat&amp;gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;InnerCat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Creates an uninitialized place
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new_uninit&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;(MaybeUninit::uninit())
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Initializes the fields in-place
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new_init&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; this = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut_ptr&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ (&amp;amp;raw &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;(*this).age).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(age) };
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; this = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;assume_init_ref&lt;&#x2F;span&gt;&lt;span&gt;() };
&lt;&#x2F;span&gt;&lt;span&gt;        this.age
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Drop &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;assume_init_drop&lt;&#x2F;span&gt;&lt;span&gt;() }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; cat = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Cat::new_uninit() };
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ cat.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;new_init&lt;&#x2F;span&gt;&lt;span&gt;() };
&lt;&#x2F;span&gt;&lt;span&gt;    assert_eq!(cat.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;(), &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The placing crate also supports desugaring types that return &lt;code&gt;Result&lt;&#x2F;code&gt;, &lt;code&gt;Box&lt;&#x2F;code&gt;,
and &lt;code&gt;Arc&lt;&#x2F;code&gt;. As well as includes support for nesting constructors, where you end
up calling a &lt;code&gt;#[placing] fn&lt;&#x2F;code&gt; from a &lt;code&gt;#[placing] fn&lt;&#x2F;code&gt;. This is why I’m fairly confident this should end up working out.&lt;&#x2F;p&gt;
&lt;p&gt;The main limitation of the crate is that it doesn’t yet support traits. I
started adding support for that, but ended up running out of time. This is the
reason why if you look at the codegen in the crate you’ll see a &lt;code&gt;PLACING: bool&lt;&#x2F;code&gt; const
generic inserted everywhere. It isn’t particularly useful yet, but now you
know why it’s there.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;thinking-in-placing-functions&quot;&gt;Thinking in placing functions&lt;&#x2F;h2&gt;
&lt;p&gt;Placing functions draw their inspiration from two other language features:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Super Let (Rust Nightly)&lt;&#x2F;strong&gt;: is an experimental feature that enables &lt;a href=&quot;https:&#x2F;&#x2F;blog.m-ou.se&#x2F;super-let&#x2F;&quot;&gt;temporary lifetime extensions&lt;&#x2F;a&gt;. This allows variables to be created in the enclosing scope.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Guaranteed Copy Elision (C++ 17)&lt;&#x2F;strong&gt;: sometimes also called &lt;a href=&quot;https:&#x2F;&#x2F;devblogs.microsoft.com&#x2F;cppblog&#x2F;guaranteed-copy-elision-does-not-elide-copies&#x2F;&quot;&gt;“deferred temporary materialization”&lt;&#x2F;a&gt; guarantees that structs are always constructed in the caller’s scope.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If &lt;code&gt;super let&lt;&#x2F;code&gt; operates on block scopes, you can think of placing functions as
operating across function boundaries. And if guaranteed copy elision is an
automated guarantee that applies to &lt;em&gt;all&lt;&#x2F;em&gt; functions, you can think of placing
functions as only ever applying to functions that have been explicitly opted
into this feature.&lt;&#x2F;p&gt;
&lt;p&gt;The design of placing functions attempts to balance three core constraints:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Control&lt;&#x2F;strong&gt;: in certain cases emplacement already happens through optimizations (e.g. inlining). An emplacement language feature must &lt;em&gt;guarantee&lt;&#x2F;em&gt; it emplaces, or else fail compilation.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Integration&lt;&#x2F;strong&gt;: C++’s guaranteed copy elision shows just how broadly applicable emplacement really is. That means the initial upper bound for this language feature is every single function with a return type. That’s incredibly broad, and we need to ensure it integrates closely and easily with the rest of the language.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Compatibility&lt;&#x2F;strong&gt;: Rust’s stdlib makes strong backwards-compatibility guarantees. We will want it to be able to make use of emplacement &lt;em&gt;without&lt;&#x2F;em&gt; breaking backwards compat. This means we cannot mint new traits just to support emplacement, or add new APIs specifically to emplace.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;It would be a mistake to think of emplacement as a feature with narrow
applicability; C++ provides evidence emplacement is relevant to almost every
constructor&lt;&#x2F;strong&gt;. The right way to think about emplacement is to assume it has a
maximally broad upper bound. But then start designing and implementing a minimal
subset. While we may eventually find limitations or cases where emplacement
isn’t possible; that will be something we prove out through implementation.&lt;&#x2F;p&gt;
&lt;p&gt;This is why I believe we should model “emplacement” more like an effect, and not
like a different kind of language feature. I think of placing functions as
somewhere between const functions and async functions. They change the codegen
of the function, not entirely unlike the generator transform we use for &lt;code&gt;async&lt;&#x2F;code&gt;
and &lt;code&gt;gen&lt;&#x2F;code&gt;. But it never actually lowers to another type we can observe in the
type system, which makes it very similar to &lt;code&gt;const&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;prior-art-in-rust&quot;&gt;Prior Art in Rust&lt;&#x2F;h2&gt;
&lt;p&gt;As I was getting ready to publish this post I ended up talking a little more
with Sy Brand about placing functions, C++, and ABIs. It turns out: Rust already
guarantees emplacement in a number of cases. Consider for example the following code:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;A {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i64&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i64&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i64&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;d&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i64&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;e&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i64&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;A {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; A {
&lt;&#x2F;span&gt;&lt;span&gt;        A {
&lt;&#x2F;span&gt;&lt;span&gt;            a: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;42&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            b: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;69&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            c: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4269&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            d: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;6942&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            e: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;696942&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When we compile this for the SYSV ABI on x86, it outputs the following
assembly (&lt;a href=&quot;https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;MeY76Ys9z&quot;&gt;godbolt&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;asm&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-asm &quot;&gt;&lt;code class=&quot;language-asm&quot; data-lang=&quot;asm&quot;&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;example::A::new::hd00831bc57a4b613:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mov &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;rax&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;rdi
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mov &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;qword ptr &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;rdi&lt;&#x2F;span&gt;&lt;span&gt;], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;42
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mov &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;qword ptr &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;rdi &lt;&#x2F;span&gt;&lt;span&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span&gt;], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;69
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mov &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;qword ptr &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;rdi &lt;&#x2F;span&gt;&lt;span&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4269
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mov &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;qword ptr &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;rdi &lt;&#x2F;span&gt;&lt;span&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;24&lt;&#x2F;span&gt;&lt;span&gt;], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;6942
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mov &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;qword ptr &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;rdi &lt;&#x2F;span&gt;&lt;span&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;32&lt;&#x2F;span&gt;&lt;span&gt;], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;696942
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;ret
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This assembly is writing directly to pointer offsets provided to the function.
In other words: this function is emplacing. And it’s actually guaranteed to do
that, as defined in the &lt;a href=&quot;https:&#x2F;&#x2F;refspecs.linuxbase.org&#x2F;elf&#x2F;x86_64-abi-0.99.pdf&quot;&gt;x86 SYSV ABI
spec&lt;&#x2F;a&gt;, section 3.2.3:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;[!quote]
If the type has class MEMORY, then the caller provides space for the return
value and passes the address of this storage in &lt;code&gt;%rdi&lt;&#x2F;code&gt; as if it were the first
argument to the function. In effect, this address becomes a “hidden” first argument
This storage must not overlap any data visible to the callee through
other names than this argument.
On return &lt;code&gt;%rax&lt;&#x2F;code&gt; will contain the address that has been passed in by the
caller in &lt;code&gt;%rdi&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;A hidden first argument that’s passed to functions? That sure sounds a lot like
how the desugaring for placing functions is intended to work. In fact, C++’s
guaranteed copy elision makes use of this very same feature. Section 3.2.3
states the following:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;If a C++ object has either a non-trivial copy constructor or a non-trivial
destructor 11, it is passed by invisible reference (the object is replaced in the
parameter list by a pointer that has class INTEGER) 12.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This is all incredibly similar to what I’m proposing, but happening
automatically at the ABI level rather than transparently at the language level. It also begs the question:  how easy it would be to modify rustc&#x27;s ABI lowering code for x64 to just say &lt;em&gt;&quot;if the type was declared with the &lt;code&gt;placing&lt;&#x2F;code&gt; attribute, it&#x27;s always classified as MEMORY”&lt;&#x2F;em&gt;?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;q-a&quot;&gt;Q&amp;amp;A&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;what-about-placing-arguments&quot;&gt;What about placing arguments?&lt;&#x2F;h3&gt;
&lt;p&gt;So far this post has only discussed placing in relation to return types. For our
goal of preserving express compatibility with the existing stdlib, placing
return types are not enough. Back in March Eric Holk and Tyler Mandry argued
that we’ll also want to have some form of placing &lt;em&gt;arguments&lt;&#x2F;em&gt; (or at least the
capability that enables us to do this). So let’s use &lt;code&gt;Box::new&lt;&#x2F;code&gt; as our example to
show why. Without placing arguments, the best we could do would be to define
some form of &lt;code&gt;Box::new_with&lt;&#x2F;code&gt; function that takes a placing closure:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; Box&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The existing default constructor
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;: T) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ ... }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The newly introduced `placing` constructor
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new_with&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;F&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;: F) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;        F: #[placing] FnOnce() -&amp;gt; T,
&lt;&#x2F;span&gt;&lt;span&gt;    { ... }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;new_with&lt;&#x2F;code&gt; constructor is always preferable to the &lt;code&gt;new&lt;&#x2F;code&gt; constructor
because it guarantees the absence of intermediate stack copies. This will lead
to an effective deprecation &lt;code&gt;Box::new&lt;&#x2F;code&gt;. If not outright, then likely first by way of &lt;em&gt;”best practices”&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The way to solve this would be to enable &lt;code&gt;Box::new&lt;&#x2F;code&gt; to act as the receiver of
values which need to be emplaced. This would be done by requiring annotations
not at the function level, but at the argument&#x2F;return-type level. Keeping with our &lt;code&gt;#[placing]&lt;&#x2F;code&gt; placeholder notation, we can imagine it looking something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Original
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; Box&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `Box::new` here takes type `T` and
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; constructs it in-place on the heap
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;: #[placing] T) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ ... }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I expect the desugaring of this will likely look somewhat similar to &lt;a href=&quot;https:&#x2F;&#x2F;hackmd.io&#x2F;@aliceryhl&#x2F;BJutRcPblx&quot;&gt;Alice
Ryhl’s in-place initialization RFC&lt;&#x2F;a&gt;,
desugaring to some form of &lt;code&gt;impl Emplace&lt;&#x2F;code&gt; trait. But crucially: this would only
be observable within the implementation, and not to any of the callers.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Desugared
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Write a value to a place.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Emplace&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;emplace&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;slot&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut&lt;&#x2F;span&gt;&lt;span&gt; T);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; Box&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;: impl Emplace&amp;lt;T&amp;gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; this = Box::&amp;lt;T&amp;gt;::new_uninit(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 1. create the place
&lt;&#x2F;span&gt;&lt;span&gt;        x.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;emplace&lt;&#x2F;span&gt;&lt;span&gt;(this.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut_ptr&lt;&#x2F;span&gt;&lt;span&gt;());          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 2. init the value
&lt;&#x2F;span&gt;&lt;span&gt;        Ok(this.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;assume_init&lt;&#x2F;span&gt;&lt;span&gt;())                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 3. all done
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now the reason why I’ve put this under Q&amp;amp;A is because I haven’t yet figured out
the finer language rules here since I haven’t implemented this yet. &lt;strong&gt;As a core
design constraint: invoking a function that takes placing arguments should be no
different from a regular function. This is needed to keep APIs
backwards-compatible.&lt;&#x2F;strong&gt; What should make this special is that functions with
placing arguments and placing return types should work together to emplace.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-about-borrows-local-lifetime-extensions&quot;&gt;What about borrows &#x2F; local lifetime extensions?&lt;&#x2F;h3&gt;
&lt;p&gt;In her post on &lt;a href=&quot;https:&#x2F;&#x2F;blog.m-ou.se&#x2F;super-let&#x2F;#super-let&quot;&gt;super let&lt;&#x2F;a&gt;, Mara
provides a clear example for when temporary lifetime extensions are useful. Here
&lt;code&gt;Writer::new&lt;&#x2F;code&gt; takes an &lt;code&gt;&amp;amp;&#x27;a File&lt;&#x2F;code&gt;, and we need  a feature like &lt;code&gt;super let&lt;&#x2F;code&gt; to
create an instance of &lt;code&gt;File&lt;&#x2F;code&gt; that outlives the scope of the block:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; writer = {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;opening file...&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; filename = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;super let&lt;&#x2F;span&gt;&lt;span&gt; file = File::create(filename).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    Writer::new(&amp;amp;file)
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The return type &lt;code&gt;Writer&lt;&#x2F;code&gt; here must have a lifetime to be able to reference
&lt;code&gt;super let file&lt;&#x2F;code&gt;. But it can’t be a normal lifetime, since it doesn’t adhere to
the usual rules. Without specifying any of the concrete rules, this lifetime has
been dubbed &lt;code&gt;&#x27;super&lt;&#x2F;code&gt;. From the perspective of the block this behaves not unlike
&lt;code&gt;&#x27;static&lt;&#x2F;code&gt; - though crucially it is not the same as &lt;code&gt;&#x27;static&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now the question is: how can we represent this block as a function instead?
Because it makes sense that we would want to eventually be able to factor out
functionality from blocks into functions. We’d probably want to do that using a
&lt;code&gt;&#x27;super&lt;&#x2F;code&gt; lifetime, like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Original
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;create_writer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;filename&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Writer&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;super&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;opening file...&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;super let&lt;&#x2F;span&gt;&lt;span&gt; file = File::create(filename).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    Writer::new(&amp;amp;file)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note how &lt;code&gt;Writer&lt;&#x2F;code&gt; itself does not require a &lt;code&gt;#[placing]&lt;&#x2F;code&gt; annotation: it’s okay
that we copy it out of the function. The only important part is that  &lt;code&gt;file&lt;&#x2F;code&gt;
outlives the current scope. The desugaring for this is quite fun, even if we
can’t yet represent it in the type system. What we need to do here is ensure
that &lt;code&gt;file&lt;&#x2F;code&gt; is constructed in-place in the caller’s scope. And once initialized
we can reference it using a blank&#x2F;unsafe lifetime in our return type. I haven’t
actually checked this, but I believe this is a valid desugaring:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Desugared
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;create_writer&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;filename&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;file&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a mut &lt;&#x2F;span&gt;&lt;span&gt;MaybeUninit&amp;lt;File&amp;gt;) -&amp;gt; Writer&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;opening file...&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; file = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(File::create(filename).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;()) };
&lt;&#x2F;span&gt;&lt;span&gt;    Writer::new(file)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This however needs to be paired with a function prelude on invocation to create
the place for &lt;code&gt;file&lt;&#x2F;code&gt;. We can therefore imagine the invocation of this function
looking something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; with syntactic sugar
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; writer = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;create_writer&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello.text&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; desugared
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; file = MaybeUninit::uninit();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; writer = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;create_writer&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello.text&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; file);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;what-about-pinning&quot;&gt;What about pinning?&lt;&#x2F;h3&gt;
&lt;p&gt;Once we have emplacement in the language, most of the reasons for &lt;code&gt;Pin&lt;&#x2F;code&gt; being
the way it is kind of fall away. But there is a gap between having emplacement,
and then also having &lt;code&gt;!Move&lt;&#x2F;code&gt;, and so we do need to have some form of
compatibility with &lt;code&gt;Pin&lt;&#x2F;code&gt;. Luckily the &lt;code&gt;Pin&lt;&#x2F;code&gt; type is just a special-case of the
previous lifetime extension example.&lt;&#x2F;p&gt;
&lt;p&gt;What’s neat about placing functions is that it would allow us to replace the &lt;code&gt;std::pin::pin!&lt;&#x2F;code&gt; macro with a &lt;code&gt;pin&lt;&#x2F;code&gt; free-function, using the &lt;code&gt;&#x27;super&lt;&#x2F;code&gt; lifetime:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Original
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;pin&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;t&lt;&#x2F;span&gt;&lt;span&gt;: T) -&amp;gt; Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;super mut&lt;&#x2F;span&gt;&lt;span&gt; T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;super let mut&lt;&#x2F;span&gt;&lt;span&gt; t = t;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Pin::new_uninit(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; t) }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;All the desugaring needs to do to make this work is change the function to take an additional
slot &lt;code&gt;MaybeUninit&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; that we can write our value into. This allows us to extend
the lifetime, after which we can reference it in our return type like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Desugared
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;pin&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;t&lt;&#x2F;span&gt;&lt;span&gt;: T, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;slot&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a mut &lt;&#x2F;span&gt;&lt;span&gt;MaybeUninit&amp;lt;T&amp;gt;) -&amp;gt; Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a mut&lt;&#x2F;span&gt;&lt;span&gt; T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; t = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ slot.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(t) };
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Pin::new_uninit(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; t) }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;are-annotations-necessary&quot;&gt;Are annotations necessary?&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;pull&#x2F;2884&quot;&gt;RFC 2884: Placement by Return&lt;&#x2F;a&gt;
proposed introducing C++’s Guaranteed Copy Elision rules to Rust almost as-is. I appreciate this
RFC because it has the right idea about the scope of the changes, and does it
solely by changing the meaning of &lt;code&gt;return&lt;&#x2F;code&gt;. But where it runs into trouble is
that it &lt;em&gt;only&lt;&#x2F;em&gt; changes the meaning of &lt;code&gt;return&lt;&#x2F;code&gt;. And so instead of adding
placement to e.g. &lt;code&gt;Box::new&lt;&#x2F;code&gt;, it needs to add a new method &lt;code&gt;Box::new_with&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Fundamentally there are three kinds of placement we’re interested in:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Placing return types&lt;&#x2F;strong&gt;: where we want a to avoid copying the type returned from a function. For example if we want a referentially-stable constructor.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Placing function arguments&lt;&#x2F;strong&gt;: where we want to avoid copying an argument passed into a function. For example: to when constructing a type on the heap.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Lifetime extensions&lt;&#x2F;strong&gt;: where we want to reference a local variable from a local type which will outlive the current scope (lifetime extension). For example: when pinning.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Even if C++’s Guaranteed Copy Elision should be our ultimate goal; annotations
allow us to get there incrementally. Placing return types are fairly easy.
Placing function arguments are a little harder. And lifetime extensions will be
harder still. Being able to opt into this via explicit annotations means we can
start small and gradually build up.&lt;&#x2F;p&gt;
&lt;p&gt;For something as broad as “functions with arguments or return types” that seems
like the right way to start. And if for some reason this feature ends up being
so successful we’ll want to annotate nearly every function with it, changing
defaults seems like something that could be done over an edition if we wanted
to.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-about-self-referential-types&quot;&gt;What about self-referential types?&lt;&#x2F;h3&gt;
&lt;p&gt;I’ve written at length about &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;self-referential-types&#x2F;&quot;&gt;self-referential types&lt;&#x2F;a&gt; before. Once we have placing functions, we end up with three components for generalized self-referential types are:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Placing functions&lt;&#x2F;strong&gt;: so we can construct a type in a stable position in memory&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Self-lifetimes&lt;&#x2F;strong&gt;: so you can declare that some field borrows from some other field.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Partial constructors&lt;&#x2F;strong&gt;: so you can start by initializing the owned data first, and initialize the references to that data second.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;We’ve already seen placing functions. Self-lifetimes would allow fields to refer
to data contained in other fields, which would probably look something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: String,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;self&lt;&#x2F;span&gt;&lt;span&gt;.data &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← references `self.data`
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And partial constructors would allow you to construct types in multiple phases.
For example, here we first initialize the field &lt;code&gt;data&lt;&#x2F;code&gt; in &lt;code&gt;Cat&lt;&#x2F;code&gt;. And then we
take the string contained within, and do some crude parsing to interpret
everything up until the first space as the cat’s name:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new_cat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: String) -&amp;gt; Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; cat = Cat { data, .. };
&lt;&#x2F;span&gt;&lt;span&gt;    cat.name = cat.data.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39; &amp;#39;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    cat
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Once we have this, we can of course combine it with the lifetime extension
examples we’ve shown before to ensure that the type remains in a stable memory
location. But crucially: this is also forward-compatible with alternative
mechanisms for referential stability such as the &lt;code&gt;Move&lt;&#x2F;code&gt; auto-trait.&lt;&#x2F;p&gt;
&lt;p&gt;As a side note: partial constructors are basically the same feature as &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;syntactic-musings-on-view-types&#x2F;&quot;&gt;view
types and pattern
types&lt;&#x2F;a&gt;. It’s
still the same general refinement feature, but now with an added rule that we
can go from a refinement type back to the original type by populating its
fields. Assigment here takes the place of an inverse &lt;code&gt;match&lt;&#x2F;code&gt; if you will.&lt;&#x2F;p&gt;
&lt;p&gt;What’s nice about this design is that these features are all orthogonal, but
complimentary. Emplacement is useful even without partial initialization. And
partial initialization (refinement) is useful even without self-referential
lifetimes. Features complimenting each other in this way to me is the hallmark
of good language design. It means it generalizes beyond just a niche use case.
But simultaneously becomes even more useful when combined with other features.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;why-not-directly-rely-on-init-t-or-out&quot;&gt;Why not directly rely on &lt;code&gt;Init&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; or &lt;code&gt;&amp;amp;out&lt;&#x2F;code&gt;?&lt;&#x2F;h3&gt;
&lt;p&gt;Both the &lt;code&gt;Init&lt;&#x2F;code&gt; type and &lt;code&gt;&amp;amp;out&lt;&#x2F;code&gt; parameters feature are backwards-incompatible to
add to existing types and interfaces. This is a problem, because placement is
broadly applicable: we know from C++ 17 that virtually every constructor wants to be
placing. And we can’t reasonably rewrite every function returning &lt;code&gt;-&amp;gt; T&lt;&#x2F;code&gt; to instead
return &lt;code&gt;-&amp;gt; Init&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; or take &lt;code&gt;&amp;amp;out T&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 1. Original signature
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new_cat&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Cat { ... }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 2. Using `Init`, changes the signature
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new_cat&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Init&amp;lt;Cat&amp;gt; { ... }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 3. Using `&amp;amp;out`, changes the signature
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new_cat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;out Cat) { ... }
&lt;&#x2F;span&gt;&lt;span&gt; 
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 3. Using `#[placing]`, preserves the signature
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;placing&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new_cat&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Cat { ... }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That doesn’t mean that these designs are inherently broken or incorrect; far
from it actually. But because they seem to assume a different scope for the
design, it naturally means those designs are operating with a different set of
design constraints - in turn leading to different designs.&lt;&#x2F;p&gt;
&lt;p&gt;I believe that &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;pull&#x2F;2884&quot;&gt;RFC 2884: Placement by
Return&lt;&#x2F;a&gt; by PoignardAzur had the
right idea. In order for Rust to be competitive with C++, we need to be able to
guarantee most constructors can emplace. And in order to do that, we can’t
require people to rewrite their code.&lt;&#x2F;p&gt;
&lt;p&gt;However, &lt;a href=&quot;https:&#x2F;&#x2F;hackmd.io&#x2F;@aliceryhl&#x2F;BJutRcPblx&quot;&gt;the Init RFC&lt;&#x2F;a&gt; has
some great ideas about how to emplace function arguments. Which is something
that RFC 2884 didn’t have a good answer to. I believe that Rust’s strength lies
in its ability to distill different ideas and synthesize them into something
new. I believe that we can arrive at something truly great if we combine &lt;code&gt;super let&lt;&#x2F;code&gt;, placement-by-return, &lt;code&gt;Init&lt;&#x2F;code&gt;, and ensure it is backwards-compatible.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;can-placing-functions-be-nested&quot;&gt;Can placing functions be nested?&lt;&#x2F;h3&gt;
&lt;p&gt;Yes - placing functions called in a return position should be able to compose.
For the language feature should be relatively straight-forward when calling one
placing function inside of another in the return position:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Foo {}
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;placing&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;inner&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Foo {
&lt;&#x2F;span&gt;&lt;span&gt;    Foo {} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← 1. Constructed in the caller&amp;#39;s scope
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;placing&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;outer&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Foo {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;inner&lt;&#x2F;span&gt;&lt;span&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← 2. Forwards the emplacement to its caller
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This itself is reminiscent of C++’s guaranteed copy elision guarantees, which
are composable through functions. That is because in C++ temporaries are only
materialized into real objects at the end of a call chain, enabling arbitrarily
deep composition. For Rust it’s important that we maintain this same property,
including when wrapping and composing types:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Foo {}
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;placing&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;inner&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Foo {
&lt;&#x2F;span&gt;&lt;span&gt;    Foo {} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← 1. Constructed in the caller&amp;#39;s scope
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Bar(Foo)
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;placing&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;outer&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Bar {
&lt;&#x2F;span&gt;&lt;span&gt;    Bar(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;inner&lt;&#x2F;span&gt;&lt;span&gt;()) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← 2. Emplaces Bar in the caller, and Foo in Bar
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this example &lt;code&gt;Bar&lt;&#x2F;code&gt; is constructed in the caller’s scope, and as part of
initialization it invokes and emplaces &lt;code&gt;Foo&lt;&#x2F;code&gt; inside of it. I stopped working on
the placing crate before implementing this, but for this desugaring to work all
we need to do is for the “place” used by the &lt;code&gt;inner&lt;&#x2F;code&gt; function to by placed
inside of the “place” used by the &lt;code&gt;outer&lt;&#x2F;code&gt; function.&lt;&#x2F;p&gt;
&lt;p&gt;The most complex kind of composition is when we start involving temporaries.
Consider the following example which constructs a type in the first function,
mutates it in the second function, and finally uses it in a third function:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A Cat which is constructed in place and can meow.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat {}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;placing&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: String) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ .. }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;set_name&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) { .. }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;meow&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) { .. }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Construct a value.
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;placing&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;first&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; name = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Nori&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    Cat::new(name) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← 1. Emplaced in the caller
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Mutate the value.
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;placing&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;second&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;super let mut&lt;&#x2F;span&gt;&lt;span&gt; cat = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;first&lt;&#x2F;span&gt;&lt;span&gt;();        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← 2. Emplaced in the caller
&lt;&#x2F;span&gt;&lt;span&gt;    cat.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;set_name&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Chashu&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;()); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← 3. Mutated
&lt;&#x2F;span&gt;&lt;span&gt;    cat                                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← 4. Logically returned
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Use the value.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;third&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cat = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;second&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← 5. Placed on-stack here
&lt;&#x2F;span&gt;&lt;span&gt;    cat.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;meow&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We need to have some way to emplace temporaries that we later logically return
from the caller. The &lt;code&gt;super let&lt;&#x2F;code&gt; feature seems like it would particularly well
for this. In the &lt;code&gt;&#x27;move&lt;&#x2F;code&gt; example we were returning a reference to a &lt;code&gt;super let&lt;&#x2F;code&gt;
value from a function. But I think it would make a lot of sense if we could use
&lt;code&gt;super let&lt;&#x2F;code&gt; to return logically owned values from a function too, as shown here.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;This post introduces a design for placing functions: a declarative addition to
Rust that enables types to be constructed in-place. &lt;strong&gt;Unlike alternative APIs such
as &lt;code&gt;Init&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; and &lt;code&gt;&amp;amp;out&lt;&#x2F;code&gt;, placing functions are designed to keep function
signatures intact, enabling existing functions and APIs to be annotated as
retroactively.&lt;&#x2F;strong&gt; In other words: placing functions were designed to prioritize
backwards-compatibility.&lt;&#x2F;p&gt;
&lt;p&gt;The placing functionality has been prototyped in the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yoshuawuyts&#x2F;placing&quot;&gt;placing
crate&lt;&#x2F;a&gt;. Even though this crate was
designed with limited time and entirely using procedural macros, it should be
sufficient to prove the feasibility of a language feature.&lt;&#x2F;p&gt;
&lt;p&gt;While placing functions are the most important placement-related feature, they
are not the only one. There are three kinds of placing functions total that need
to be addressed:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Placing return types&lt;&#x2F;strong&gt;: where we want a to avoid copying the type returned from a function. For example if we want a referentially-stable constructor.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Lifetime extensions&lt;&#x2F;strong&gt;: where we want to reference a local variable from a local type which will outlive the current scope (lifetime extension). For example: when pinning.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Placing function arguments&lt;&#x2F;strong&gt;: where we want to avoid copying an argument passed into a function. For example: to when constructing a type on the heap.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;A complete solution should address all three of these uses. Placing functions
only directly enables placing return types, but in the discussion section we’ve
also discussed how we could extend this to include lifetime extensions and
placing function arguments.&lt;&#x2F;p&gt;
&lt;p&gt;When discussing emplacement it’s important to consider both intra-function and
inter-function variants. The experimental &lt;code&gt;super let&lt;&#x2F;code&gt; feature only works
&lt;em&gt;within&lt;&#x2F;em&gt; functions today (intra-function). With placing functions working very
similarly, enabling similar functionality to work &lt;em&gt;between&lt;&#x2F;em&gt; functions too
(inter-function). A good design should make both variants easy, convenient, and
interoperable.&lt;&#x2F;p&gt;
&lt;p&gt;In this post we’ve also explained why the scope for emplacement is broad: in C++
constructors guarantee emplacement by default. And given Rust wants to have
performance that’s competitive with C++, we have to assume that most functions
will eventually want to make that guarantee as well. And the only realistic way
to achieve that is if we can guarantee emplacement in a backwards-compatible
way.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Sy Brand for reviewing earlier copies of this post and especially providing valuable feedback and clarifications about both C++’s copy elisions feature, as well as how the SYSV ABI works.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;I only had a hunch this was possible. Alice Ryhl has done the work to prove this can be done. Albeit for a slightly different, but very similar proposal.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</description>
        </item>
        <item>
            <title>Tree-Structured Concurrency II: Replacing Background Tasks With Actors</title>
            <pubDate>Wed, 02 Jul 2025 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/replacing-tasks-with-actors/</link>
            <guid>https://blog.yoshuawuyts.com/replacing-tasks-with-actors/</guid>
            <description>&lt;h2 id=&quot;structured-concurrency&quot;&gt;Structured concurrency&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;tree-structured-concurrency&#x2F;&quot;&gt;(Tree-)Structured
Concurrency&lt;&#x2F;a&gt; is neat
because it greatly simplifies concurrent programs. It greatly reduces, if not
outright eliminates the possibility of logical races due to concurrency issues. And
conceptually it’s not that hard either, as we can encode structured concurrency
with just two rules:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Every child computation (except the root) &lt;em&gt;must&lt;&#x2F;em&gt; have exactly one logical parent at any given time during execution.&lt;&#x2F;li&gt;
&lt;li&gt;Every parent computation &lt;em&gt;may&lt;&#x2F;em&gt; have multiple child computations executing concurrently at any given moment.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Every child must always have exactly one parent. But every parent may have multiple children. These two rules allow us to infer a third rule that is at the core of the system:&lt;&#x2F;p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Child computations will never outlive their parents.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;If we apply these rules, we’ll notice that the call-graph of a program will
naturally form a tree. This is nothing special, since non-concurrent programs
already work this way. If that’s not intuitive: realize that for example
flame graphs and flame charts are nothing more than a visualization of
tree-shaped data.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-background-task-problem&quot;&gt;The background task problem&lt;&#x2F;h2&gt;
&lt;p&gt;One of the most common questions people ask when learning about structured concurrency is:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“How do I run work &lt;em&gt;after&lt;&#x2F;em&gt; returning from a function?”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This is a fair question! A common example is when implementing an HTTP server: you
may want to log metrics on every request, but you don’t want to delay sending
the response until logging has completed. At which point people often reach for
unstructured concurrency in the form of &lt;em&gt;background tasks&lt;&#x2F;em&gt;, often using some
form of &lt;code&gt;task::spawn&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Some HTTP handler
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;handler&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;req&lt;&#x2F;span&gt;&lt;span&gt;: Request, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;_context&lt;&#x2F;span&gt;&lt;span&gt;: ()) -&amp;gt; Result&amp;lt;Response&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Get the body from a request
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; body = req.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;body&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_to_string&lt;&#x2F;span&gt;&lt;span&gt;()?;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create a detached background task that
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; does some work in the background
&lt;&#x2F;span&gt;&lt;span&gt;    task::spawn(async {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;background_work&lt;&#x2F;span&gt;&lt;span&gt;(body).await.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    });
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Construct a response and return
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; it from the handler
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(Response::Ok())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this example, &lt;code&gt;task::spawn&lt;&#x2F;code&gt; creates a background task which is not owned by
any parent. This violates the second rule of structured concurrency: every
computation should always have one logical parent. We can see this being a
problem if &lt;code&gt;background_work&lt;&#x2F;code&gt; were to complete unsuccessfully. Right now if it
fails we have no way to propagate the error or retry the operation, so all we
can realistically do is let it crash.&lt;&#x2F;p&gt;
&lt;p&gt;In this example we also have no way of cancelling the work done in the task
since it’s not rooted in any logical parent. But despite those issues, use case
itself is also a very reasonable one: we shouldn’t have to wait for background
work to finish before sending off a response. So: what do we do?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-actor-pattern&quot;&gt;The actor pattern&lt;&#x2F;h2&gt;
&lt;p&gt;What we want is for work to happen in the background, while simultaneously also
being rooted in some parent computation. I believe the right way to solve this
is by using actors: types that we can send data and will schedule work for us.&lt;&#x2F;p&gt;
&lt;p&gt;In frameworks
like &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;actix&#x2F;actix&quot;&gt;actix&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;www.choo.io&#x2F;docs&#x2F;stores&quot;&gt;choo&lt;&#x2F;a&gt; this is done using &lt;em&gt;messages&lt;&#x2F;em&gt; that are
dispatched using channels or event emitters. But languages like Swift have
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;swiftlang&#x2F;swift-evolution&#x2F;blob&#x2F;main&#x2F;proposals&#x2F;0306-actors.md#interleaving-execution-with-reentrant-actors&quot;&gt;actor
support&lt;&#x2F;a&gt;
built directly into the language, and rely on methods instead of messages.&lt;&#x2F;p&gt;
&lt;p&gt;But for what we’re trying to do here we don’t really need any fancy libraries or
frameworks: we can easily build our own actors using structs, impl blocks, and
channels. Here is a basic template you can use to implement your own actors
with. Without comments this comes out to maybe 15 lines total:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Using the `async-channel` and
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `futures-concurrency` libraries
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_channel::{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self &lt;&#x2F;span&gt;&lt;span&gt;as channel, Sender, Receiver};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_concurrency::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The type of data we will send to our actor.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; This is just a simple alias to our HTTP
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; framework&amp;#39;s `Body` type.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Message = Body;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Our custom actor type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Actor(Receiver&amp;lt;Message&amp;gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A handle to the actor which can be
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; used to schedule messages with.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Handle = Sender&amp;lt;Message&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Actor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Create a new `Actor` instance
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;capacity&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;, Handle) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(sender, receiver) = channel::bounded(capacity);
&lt;&#x2F;span&gt;&lt;span&gt;        (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;(receiver), sender)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Start listening for incoming messages
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; and handle them concurrently
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Using `ConcurrentStream` from `futures-concurrency`
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; to take work from the channel and execute it
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; concurrently. To bound the amount of concurrency,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; you can use the provided `.limit` combinator.
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;co&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_for_each&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;msg&lt;&#x2F;span&gt;&lt;span&gt;| {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Work is scheduled here
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;background_work&lt;&#x2F;span&gt;&lt;span&gt;(body).await?;
&lt;&#x2F;span&gt;&lt;span&gt;            Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;        }).await?;
&lt;&#x2F;span&gt;&lt;span&gt;        Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now to use this we need to create an instance, run it concurrently with our HTTP
server, and make sure request handlers in the server have access to it. I’m most
familiar with the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tide&#x2F;latest&#x2F;tide&#x2F;&quot;&gt;Tide HTTP framework&lt;&#x2F;a&gt; so
I’ll be using that here, but your favorite framework probably allows you to do
something similar. Here is the way to tie this all together:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_concurrency::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;async_main&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; server::Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create an instance of our actor
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(actor, handle) = Actor::new();
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create an instance of our server
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; and pass it the actor handle
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; app = Server::with_context(handle);
&lt;&#x2F;span&gt;&lt;span&gt;    app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;submit&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;post&lt;&#x2F;span&gt;&lt;span&gt;(handler);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Start both the actor and the server
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; and execute them concurrently
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;listen&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = actor.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    (a, b).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_join&lt;&#x2F;span&gt;&lt;span&gt;().await?;
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And now that our server has a handle, we can change our request handler function
to schedule work on the actor rather than in a dangling task:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;handler&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;req&lt;&#x2F;span&gt;&lt;span&gt;: Request, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;handle&lt;&#x2F;span&gt;&lt;span&gt;: Handle) -&amp;gt; Result&amp;lt;Response&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; body = req.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;body&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_to_string&lt;&#x2F;span&gt;&lt;span&gt;()?;
&lt;&#x2F;span&gt;&lt;span&gt;    handle.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(body).await?; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Send work to the actor
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(Response::Ok())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While this still relies on performing an async operation that may potentially
fail, this is still meaningfully different. Rather than waiting for the work to
have been &lt;em&gt;completed&lt;&#x2F;em&gt;, all we’re now waiting for is for the work to have been
&lt;em&gt;enqueued&lt;&#x2F;em&gt;. And unless something is going horribly wrong in the system, that
should happen virtually instantly. And if for some reason it doesn’t: that’s why we always add timeouts to our computations right? &lt;a href=&quot;https:&#x2F;&#x2F;www.usenix.org&#x2F;legacy&#x2F;events&#x2F;hotos03&#x2F;tech&#x2F;full_papers&#x2F;candea&#x2F;candea.pdf&quot;&gt;…right?&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-are-actors-different-from-globals&quot;&gt;How are actors different from globals?&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;This section was added on 2025-06-02, after publishing the post.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I’ve had a number of people ask what the difference is between the actor pattern
shown in this post, and the global task pool that manages the spawned tasks.
After all: if you take the program as the root, both variants end up looking
tree-shaped.&lt;&#x2F;p&gt;
&lt;p&gt;The difference between the two is that under structured concurrency we’re not
treating the &lt;em&gt;program&lt;&#x2F;em&gt; as the root, but the &lt;em&gt;main function&lt;&#x2F;em&gt; as the root. The
actor pattern in this post turns an unreachable, global task pool into a
reachable task pool with a locality that can be managed however we like. Sy
Brand put this particularly well; paraphrasing ever so slightly:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;[…] that &quot;oh, it&#x27;s structured as long as you look at it this way&quot; smells like
&quot;well my program doesn&#x27;t leak memory since it will all be reclaimed when it
terminates&quot;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The point of structured concurrency is that everything is always managed and
reachable by having all computation existing in the same tree. This makes it
possible to &lt;em&gt;always&lt;&#x2F;em&gt; handle errors, restart instances, and shut things down gracefully.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we’ve answered one of the most common questions people have when
first encountering structured concurrency: &lt;em&gt;“How do I schedule background work
without relying on dangling tasks?”&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The simplest answer to this question are actors: types that provide some
(shareable) handle that can be used to receive work on. We’ve shown how to
define an actor in about 15 lines of code, how to integrate it with an HTTP
server, and finally using it to replace an existing background task.&lt;&#x2F;p&gt;
&lt;p&gt;I think of structured concurrency the way I think about memory safety: the more
we make it the default, the fewer concurrency issues people will have overall.
And that seems important because concurrent, asynchronous, and parallel
computing tends to some of the hardest code to reason about and debug.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;appendix-a-actor-pattern-template&quot;&gt;Appendix A: Actor pattern template&lt;&#x2F;h2&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_channel::{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self &lt;&#x2F;span&gt;&lt;span&gt;as channel, Sender, Receiver};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_concurrency::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Message = ();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Handle = Sender&amp;lt;Message&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Actor(Receiver&amp;lt;Message&amp;gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Actor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;capacity&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;, Handle) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(sender, receiver) = channel::bounded(capacity);
&lt;&#x2F;span&gt;&lt;span&gt;        (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;(receiver), sender)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;co&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_for_each&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;msg&lt;&#x2F;span&gt;&lt;span&gt;| {
&lt;&#x2F;span&gt;&lt;span&gt;            todo!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;schedule work here&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;        }).await
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</description>
        </item>
        <item>
            <title>Async Traits Can Be Directly Backed By Manual Future Impls</title>
            <pubDate>Mon, 26 May 2025 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/async-traits-can-be-directly-backed-by-manual-future-impls/</link>
            <guid>https://blog.yoshuawuyts.com/async-traits-can-be-directly-backed-by-manual-future-impls/</guid>
            <description>&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;There’s a fun little tidbit that most people don’t seem to be aware of when
writing async functions in traits (AFITs) and that is: they allow you to
directly return futures from methods. Sounds confusing? Let me illustrate what I
mean with a simple example. Assume we have an a trait &lt;code&gt;AsyncIterator&lt;&#x2F;code&gt; which has an &lt;code&gt;async fn next&lt;&#x2F;code&gt; method that is defined as follows:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;AsyncIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we wanted to define an iterator which yields an item exactly once, we would
probably write it as follows. This stores a value &lt;code&gt;T&lt;&#x2F;code&gt; in an &lt;code&gt;Option&lt;&#x2F;code&gt;, and in a
call to &lt;code&gt;next&lt;&#x2F;code&gt; we extract it and return &lt;code&gt;Some(T)&lt;&#x2F;code&gt; if we have a value, and &lt;code&gt;None&lt;&#x2F;code&gt;
if we don’t:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Yields an item exactly once
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Once&amp;lt;T&amp;gt;(Option&amp;lt;T&amp;gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; AsyncIterator &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Once&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item = T;
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Easy right? Now let’s try and write this future by hand. Rust is a systems
programming language, and so it’s important that we can drop into lower levels
of abstraction to gain additional control when needed. I consider it to be a gap
in the language whenever we can’t break through an abstraction into its
constituent parts. So let’s see what that would look like.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;naively-backing-afits-with-manual-future-impls&quot;&gt;Naively backing AFITs with manual future impls&lt;&#x2F;h2&gt;
&lt;p&gt;Ok, so what are the constituent parts of an &lt;code&gt;async fn&lt;&#x2F;code&gt;? Well, that’s mainly the
&lt;code&gt;Future&lt;&#x2F;code&gt; trait. What we want to do here is to define our own future and use
that as the basis of our implementation. All we do is deref an option, and take
its internal value - which makes it rather simple. Naively we would probably
write something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The internal `Future` impl of our `Once` iterator
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;OnceFuture&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;, T&amp;gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a mut &lt;&#x2F;span&gt;&lt;span&gt;Once&amp;lt;T&amp;gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;, T&amp;gt; Future &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Once&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;, T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output = T;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; SAFETY: we&amp;#39;re projecting into an unpinned field
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; this = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Pin::into_inner_unchecked(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) };
&lt;&#x2F;span&gt;&lt;span&gt;        Poll::Ready((&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; this.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0.0&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;())        
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Yields an item exactly once
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Once&amp;lt;T&amp;gt;(Option&amp;lt;T&amp;gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; AsyncIterator &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Once&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item = T;
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Delegate to the `OnceFuture` impl
&lt;&#x2F;span&gt;&lt;span&gt;        OnceFuture(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;).await
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There’s a lot going on all of a sudden, right? This is the low-level version of
what we wrote earlier. Or is it? If you look carefully you might notice that
we’re dealing with one extra level of indirection here. In our iterator’s main
body we wrote: &lt;code&gt;OnceFuture(self).await&lt;&#x2F;code&gt;.  In a simple benchmark the compiler
will happily optimize this. But in more complex programs the compiler may not.
And that’s an issue, because it means that switching to a lower-level
abstraction may yield worse performance.&lt;&#x2F;p&gt;
&lt;p&gt;If this was the best we could do, it would likely spell the death of AFITs in
the stdlib. It would mean that AFITs would be useful for high-level APIs that we
can implement using &lt;code&gt;async fn&lt;&#x2F;code&gt; and be happy with that. But not for &lt;em&gt;serious&lt;&#x2F;em&gt;
implementations which need to be optimized all the way, like those found in the
stdlib. And that would point us at things like &lt;code&gt;poll_*&lt;&#x2F;code&gt;-based traits which we
can more directly implement by hand.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;directly-backing-afits-with-manual-future-impls&quot;&gt;Directly backing AFITs with manual future impls&lt;&#x2F;h2&gt;
&lt;p&gt;Luckily we can trivially remove the intermediate &lt;code&gt;.await&lt;&#x2F;code&gt; call from our previous
example using a little-known AFIT feature: the ability to directly return
futures. Instead of writing &lt;code&gt;async fn next&lt;&#x2F;code&gt;, we can write that same function as
&lt;code&gt;fn next() -&amp;gt; impl Future&lt;&#x2F;code&gt;. That’s almost the same; with some minor differences:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The internal `Future` impl of our `Once` iterator
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;OnceFuture&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;, T&amp;gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a mut &lt;&#x2F;span&gt;&lt;span&gt;Once&amp;lt;T&amp;gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;, T&amp;gt; Future &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Once&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;, T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output = T;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; SAFETY: we&amp;#39;re projecting into an unpinned field
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; this = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Pin::into_inner_unchecked(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) };
&lt;&#x2F;span&gt;&lt;span&gt;        Poll::Ready((&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; this.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0.0&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;())        
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Yields an item exactly once
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Once&amp;lt;T&amp;gt;(Option&amp;lt;T&amp;gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; AsyncIterator &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Once&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item = T;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Directly returns the `OnceFuture` impl
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; impl Future&amp;lt;Output = Option&amp;lt;T&amp;gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        OnceFuture(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← no more `.await`
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Do you see the &lt;code&gt;fn next&lt;&#x2F;code&gt; impl? It now directly returns the &lt;code&gt;OnceFuture&lt;&#x2F;code&gt;. And we
can do this even though the trait definition explicitly defined the trait method
as &lt;code&gt;async fn next&lt;&#x2F;code&gt;. This means there is no intermediate &lt;code&gt;.await&lt;&#x2F;code&gt; call required
to base our AFIT-based trait on a manual future impl. Which means we’re no longer
depending on the compiler to optimize this for us to have equivalent
performance, meeting our goals of being able to manually lower the high-level
notation into its constituent parts which we can manually control.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;simple-inline-poll-state-machines&quot;&gt;Simple inline poll state machines&lt;&#x2F;h2&gt;
&lt;p&gt;The Rust stdlib provides a &lt;code&gt;future::poll_fn&lt;&#x2F;code&gt; convenience function that allows
you to create stateless (e.g. does not hold its own state across &lt;code&gt;poll&lt;&#x2F;code&gt; calls)
futures. But because it takes an &lt;code&gt;FnMut&lt;&#x2F;code&gt; closure, it can reference external
state made available to it via upvars. This allows us to rewrite the chonky manual future implementation from our last two examples as a sleek inline call to &lt;code&gt;poll_fn&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Yields an item exactly once
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Once&amp;lt;T&amp;gt;(Option&amp;lt;T&amp;gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; AsyncIterator &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Once&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item = T;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; impl Future&amp;lt;Output = Option&amp;lt;T&amp;gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        future::poll_fn(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;_cx&lt;&#x2F;span&gt;&lt;span&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;* -&amp;gt; Poll&amp;lt;Option&amp;lt;T&amp;gt;&amp;gt; *&#x2F; &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            Poll::Ready((&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.value).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;())
&lt;&#x2F;span&gt;&lt;span&gt;        })
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is incredibly convenient because it allows us to quickly write some
optimized inline poll-based state machine code inside trait implementations. Or
really: any &lt;code&gt;async&lt;&#x2F;code&gt; context. I like to think of &lt;code&gt;poll_fn&lt;&#x2F;code&gt; as a way to quickly
step into “low level async” mode, kind of like how &lt;code&gt;unsafe {}&lt;&#x2F;code&gt; allows you to
step into “raw memory mode”.&lt;&#x2F;p&gt;
&lt;p&gt;This also clearly makes the &lt;code&gt;Future&lt;&#x2F;code&gt; trait the fundamental building block of
everything &lt;code&gt;async&lt;&#x2F;code&gt;. Which is a simpler and more robust model than the
alternative &lt;code&gt;fn poll_*&lt;&#x2F;code&gt; model; under which async operations can be implemented
either in terms of &lt;code&gt;Future::poll&lt;&#x2F;code&gt;, &lt;code&gt;AsyncIterator::poll_next&lt;&#x2F;code&gt;,
&lt;code&gt;AsyncRead::poll_read&lt;&#x2F;code&gt;, and so on.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I wrote this post because most people don’t seem to be aware that AFITs can be
used like this. Though arguably it’s one of its most important capabilities. And
that’s important because as I said earlier in this post: it would be really bad
if the async trait space was bifurcated between:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AFIT-based traits&lt;&#x2F;strong&gt;: which are convenient to implement but have worse performance due to lack of control.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Poll-based traits&lt;&#x2F;strong&gt;: which are inconvenient to implement but have better performance because of the control provided&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;This post shows that AFIT-based traits are both convenient to implement, and
when desired provide the control needed to guarantee performance via manual
poll-state machine implementations.&lt;&#x2F;strong&gt; This unifies the design space for
async traits, removing the choice between “the easy API” and “the fast API”.
With AFITs the easy API &lt;em&gt;is&lt;&#x2F;em&gt; the fast API.&lt;&#x2F;p&gt;
&lt;p&gt;While we used the &lt;code&gt;AsyncIterator&lt;&#x2F;code&gt; trait as an example in this post, nothing in
this post so far has been specific to &lt;code&gt;AsyncIterator&lt;&#x2F;code&gt;. Being able to control the
future state machines of &lt;code&gt;AsyncRead&lt;&#x2F;code&gt;, &lt;code&gt;AsyncWrite&lt;&#x2F;code&gt;, and so on isn’t any less
important. But if we were to consider an AFIT-based &lt;code&gt;AsyncIterator&lt;&#x2F;code&gt; specifically
with an &lt;code&gt;async gen {}&lt;&#x2F;code&gt; feature we can see that it provides three total levels of
control, where a &lt;code&gt;poll&lt;&#x2F;code&gt;-based &lt;code&gt;AsyncIterator&lt;&#x2F;code&gt; trait only provides two &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;AFIT-based&lt;&#x2F;th&gt;&lt;th&gt;&lt;code&gt;poll_*&lt;&#x2F;code&gt;-based&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;async gen {}&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;✅&lt;&#x2F;td&gt;&lt;td&gt;✅&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;async fn&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;✅&lt;&#x2F;td&gt;&lt;td&gt;❌&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;fn poll&lt;&#x2F;code&gt; state machine&lt;&#x2F;td&gt;&lt;td&gt;✅&lt;&#x2F;td&gt;&lt;td&gt;✅&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;And all three levels of abstraction are important to be convenient to implement.
It would be wrong to pick and choose. Being able to implement async traits based
on &lt;code&gt;async fn&lt;&#x2F;code&gt; is important in cases where a high-level construct like &lt;code&gt;gen {}&lt;&#x2F;code&gt;
is not available, like with &lt;code&gt;AsyncRead&lt;&#x2F;code&gt;, and &lt;code&gt;AsyncWrite&lt;&#x2F;code&gt;. But it’s also
important for &lt;code&gt;AsyncIterator&lt;&#x2F;code&gt; to be able to implement subtrait
variants like &lt;code&gt;ExactSizeIterator&lt;&#x2F;code&gt;, and be able to implement provided methods like &lt;code&gt;fn size_hint&lt;&#x2F;code&gt;.
&lt;code&gt;async gen {}&lt;&#x2F;code&gt; doesn’t provide the ability to do either &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, and users shouldn’t be forced to write
&lt;code&gt;poll&lt;&#x2F;code&gt;-based state machines just for that.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;acknowledgements&quot;&gt;Acknowledgements&lt;&#x2F;h2&gt;
&lt;p&gt;I’d like to thank Oli Scherer for taking the time late last year to
work with me through a series of examples of AFITs backed manually implemented
futures, and explaining how they are resolved and optimized by the compiler.
That conversation is what has given me the confidence to make the claims in this
post with a degree of certainty I would otherwise not have. Oli did however not
review this post in advance, so I’m most definitely not speaking on their
behalf and any mistakes in this post will be my own.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;I’m sure with enough language magic we could provide &lt;em&gt;some&lt;&#x2F;em&gt; way to allow &lt;code&gt;fn poll_*&lt;&#x2F;code&gt;-based traits to be implemented in terms of &lt;code&gt;async fn&lt;&#x2F;code&gt;. But that require an entirely new language feature, all to just end up with a less consistent and more complicated model than if we directly base all async traits (but &lt;code&gt;Future&lt;&#x2F;code&gt;) on &lt;code&gt;async fn&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Capability-based arguments aside, I also believe that implementing traits &lt;em&gt;should&lt;&#x2F;em&gt; be easy. Like, what do you mean implementing a non-blocking iterator by hand requires a PhD in Rustology? Rust is supposed to make systems programming accessible and &lt;em&gt;understandable&lt;&#x2F;em&gt;. And that needs to apply to every level of abstraction.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</description>
        </item>
        <item>
            <title>The Waker Allocation Problem</title>
            <pubDate>Fri, 23 May 2025 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/the-waker-allocation-problem/</link>
            <guid>https://blog.yoshuawuyts.com/the-waker-allocation-problem/</guid>
            <description>&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;The entire point of futures and Rust’s async&#x2F;.await system is to introduce two
new capabilities: arbitrary concurrent execution of computations, and arbitrary
cancellation of computations. The difference between blocking and non-blocking
computation is unimportant if we then don’t also capitalize on it by scheduling
work concurrently.&lt;&#x2F;p&gt;
&lt;p&gt;But there’s a problem - In order to schedule work concurrently futures have two
bad choices in how to organize their internals:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Without allocations&lt;&#x2F;strong&gt; futures have &lt;code&gt;O(N^2)&lt;&#x2F;code&gt;(quadratic) wakeup behavior for their child futures. This means that if we schedule 1_000 futures that all wake independently and in sequence, we’ll approximate 1_000_000 total wakes &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;With allocations&lt;&#x2F;strong&gt; futures can have &lt;code&gt;O(N)&lt;&#x2F;code&gt; wakeup behavior for their child futures. This means that if we schedule 1_000 futures that all complete independently and in sequence, we’ll have 1_000 total wakes.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In Rust we’re well aware that hidden allocations are bad. But we also know that
quadratic scaling on potentially unbounded numbers of items is also bad. And
it’s bad that we’re in a position where we have to choose between both.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;efficient-concurrent-execution-requires-intermediate-wakers&quot;&gt;Efficient concurrent execution requires intermediate wakers&lt;&#x2F;h2&gt;
&lt;p&gt;Say we’re writing a manual &lt;code&gt;future::join&lt;&#x2F;code&gt; function  which takes an array of &lt;code&gt;impl Future&lt;&#x2F;code&gt; and returns an array of &lt;code&gt;Future::Output&lt;&#x2F;code&gt;. We can model the internal state
of this using an array of futures, and an array of future outputs:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A future that concurrently awaits a list of futures
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Join&amp;lt;Fut: Future, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; N: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The futures we&amp;#39;re awaiting.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;futures&lt;&#x2F;span&gt;&lt;span&gt;: [Fut; N],
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The outputs of the futures.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;outputs&lt;&#x2F;span&gt;&lt;span&gt;: [Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Fut::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt;; N],
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In order to concurrently await all futures, we have to implement the &lt;code&gt;Future&lt;&#x2F;code&gt;
trait for &lt;code&gt;Join&lt;&#x2F;code&gt;. The output type of this is &lt;code&gt;[Future::Output; N]&lt;&#x2F;code&gt;, with each
call to &lt;code&gt;poll&lt;&#x2F;code&gt; iterating over each pending future contained within. Here’s an
naive example implementation that, mostly just to provide context:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;Fut: Future, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; N: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; Future &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Join&amp;lt;Fut, N&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output = [Fut::Output; N];
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; setup the initial state
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; this = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get_unchecked_mut&lt;&#x2F;span&gt;&lt;span&gt;() };
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; all_done = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Iterate over every future until we either have all
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; values, or we still have futures pending.
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; i in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..this.futures.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Either the future is already done…
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; this.outputs[i].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_some&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;continue&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; …or we still need to poll it.
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; fut = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Pin::new_unchecked(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; this.futures[i]) };
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; fut.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(cx) {
&lt;&#x2F;span&gt;&lt;span&gt;                Poll::Ready(output) =&amp;gt; this.outputs[i] = Some(output),
&lt;&#x2F;span&gt;&lt;span&gt;                Poll::Pending =&amp;gt; all_done = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The loop is done and its time to look at our
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; results. We either still have futures pending…
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;!all_done {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;Poll::Pending;
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; …or we&amp;#39;re all done and we&amp;#39;re ready to return.
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; outputs = std::mem::replace(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; this.outputs, [None; N])
&lt;&#x2F;span&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(Option::unwrap);
&lt;&#x2F;span&gt;&lt;span&gt;        
&lt;&#x2F;span&gt;&lt;span&gt;        Poll::Ready(outputs)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you look at the core of this loop, you’ll notice that we’re iterating over
each future on every iteration - regardless of whether it called its respective
waker of not. The only futures we don&#x27;t call are the ones we already have an
output of. Practically this means that we approach &lt;code&gt;O(N^2)&lt;&#x2F;code&gt; execution: we wake
every future on every call to poll. And we do this because we don’t know which
futures were are ready and which are not.&lt;&#x2F;p&gt;
&lt;p&gt;The solution here is to create an “intermediate” or “inline” waker. Rather than
passing the caller’s waker down into all of the child futures, the &lt;code&gt;Join&lt;&#x2F;code&gt; future
should instead create its own waker(s) which can track which child futures are
ready - and only poll those. The simplest way of doing this is keeping an array of
wakers and an array of “ready” indexes. Whenever a child future calls wake, it
pushes its index to the list of ready indexes, and then calls the parent waker.
Then when the &lt;code&gt;Join&lt;&#x2F;code&gt; future is polled, all it needs to do is iterate over all
ready indexes and poll those futures. For brevity I won’t bother showing the
full implementation, just the definition itself:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A future that concurrently awaits a list of futures
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Join&amp;lt;Fut: Future, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; N: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The futures we&amp;#39;re awaiting.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;futures&lt;&#x2F;span&gt;&lt;span&gt;: [Fut; N],
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The outputs of the futures.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;outputs&lt;&#x2F;span&gt;&lt;span&gt;: [Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Fut::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt;; N],
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Keeps a waker per child future
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;wakers&lt;&#x2F;span&gt;&lt;span&gt;: [ChildWaker; N],
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Tracks which child futures should be woken
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;indexes&lt;&#x2F;span&gt;&lt;span&gt;: Arc&amp;lt;[AtomicBool; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;N&lt;&#x2F;span&gt;&lt;span&gt;]&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A waker associated with a specific child future
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;ChildWaker {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The index of the child future in the index list
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;index&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A handle to the parent waker, passed to the struct
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;parent_waker&lt;&#x2F;span&gt;&lt;span&gt;: Waker,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Tracks which child futures should be woken. Intended
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; to be indexed into using `index` inside `Wake`.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;indexes&lt;&#x2F;span&gt;&lt;span&gt;: Arc&amp;lt;[AtomicBool; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;N&lt;&#x2F;span&gt;&lt;span&gt;]&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Wake &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;InlineWaker { ... }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are more efficient schemes than this one, though this is among the
simplest. And crucially: this allows us to only ever wake the futures that need
to be woken. Which is important, since waking futures may potentially be
expensive. And while we can encourage futures to be cheap to wake spuriously -
we should really just not cause spurious wakes in the first place. Because it&#x27;s
better if the burden falls on async experts writing primitives, than on every
single person implementing the future trait &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;intermediate-wakers-require-allocations&quot;&gt;Intermediate wakers require allocations&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we’ve looked at why futures want to make use of intermediate wakers,
let’s take a closer look at the waker internals. The &lt;code&gt;Future&lt;&#x2F;code&gt; trait relies on a
type called &lt;code&gt;Waker&lt;&#x2F;code&gt;, which you can think of as an &lt;code&gt;Arc&amp;lt;Fn&amp;gt;&lt;&#x2F;code&gt; pointer. Where you
can think of &lt;code&gt;Arc&lt;&#x2F;code&gt; as a fancy type of &lt;code&gt;Box&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; that can be freely cloned around
and provides shared (immutable) access to its internals. Here’s how you define a
ew &lt;code&gt;Waker&lt;&#x2F;code&gt; that will unpark the current thread when called:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::sync::Arc;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::task::{Context, Wake};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::thread::{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, Thread};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::pin::pin;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A waker that wakes up the current thread when called.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;ThreadWaker(Thread);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Wake &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;ThreadWaker {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;wake&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Arc&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unpark&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And here is how you construct an instance of that same waker. This relies on a
&lt;code&gt;From&amp;lt;Arc&amp;lt;Wake + Send + Sync + &#x27;static&amp;gt;&amp;gt;&lt;&#x2F;code&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;task&#x2F;struct.Waker.html#impl-From%3CArc%3CW%3E%3E-for-Waker&quot;&gt;impl&lt;&#x2F;a&gt;
for `Waker:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Run a future to completion on the current thread.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;block_on&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fut&lt;&#x2F;span&gt;&lt;span&gt;: impl Future&amp;lt;Output = T&amp;gt;) -&amp;gt; T {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; fut = pin!(fut);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Construct an instance of `ThreadWaker`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; t = thread::current();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; waker = Arc::new(ThreadWaker(t)).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← This allocates
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Right there, creating an instance of &lt;code&gt;Arc::new&lt;&#x2F;code&gt; means we’re allocating. In
theory we don’t &lt;em&gt;have&lt;&#x2F;em&gt; to use &lt;code&gt;Arc&lt;&#x2F;code&gt; for this either. The type
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;task&#x2F;struct.Waker.html&quot;&gt;&lt;code&gt;Waker&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; only requires
that it wraps a
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;task&#x2F;struct.RawWakerVTable.html&quot;&gt;&lt;code&gt;RawWakerVTable&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
in a way that is &lt;code&gt;Send + Sync + Clone&lt;&#x2F;code&gt;. That means in theory we could also have
a &lt;code&gt;static&lt;&#x2F;code&gt; somewhere with internal mutability, and perhaps some (embedded)
systems rely on this for their global runtimes. But in practice for inline
concurrent operations, if we’re going to be creating a &lt;code&gt;Waker&lt;&#x2F;code&gt; it’s going to
need to be based on an &lt;code&gt;Arc&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;The fact that it practically relies on allocations is not the only problem: in
single-threaded systems &lt;code&gt;Waker&lt;&#x2F;code&gt; still requires the &lt;code&gt;+ Send + Sync&lt;&#x2F;code&gt; bounds. Even
if we would end up adding a
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;task&#x2F;struct.LocalWaker.html&quot;&gt;&lt;code&gt;LocalWaker&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; type,
that still requires the original &lt;code&gt;Waker&lt;&#x2F;code&gt; type to be present. Which means we
can’t practically write portable async-based &lt;code&gt;!Send&lt;&#x2F;code&gt; libraries, because that
bound will never surface in the type system &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The reason why we have an &lt;code&gt;Arc&amp;lt;Fn&amp;gt;&lt;&#x2F;code&gt; to begin with is because the future design assumes we
might want to wrap arbitrary computation in the wakers. But I’m not sure how true that is. For example, in the
&lt;code&gt;futures-concurrency&lt;&#x2F;code&gt; library - our wakers only ever perform an
operation equivalent to flipping an atomic bool
(&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yoshuawuyts&#x2F;futures-concurrency&#x2F;blob&#x2F;1795a1ceda76c3c1c933e8fa848b7c328f66c620&#x2F;src&#x2F;utils&#x2F;wakers&#x2F;vec&#x2F;waker.rs#L24&quot;&gt;src&lt;&#x2F;a&gt;).
If we were hand-rolling our own implementation directly against e.g. the &lt;code&gt;epoll&lt;&#x2F;code&gt;
API, we wouldn’t have to pay any cost like this. What we’ve looked at in this
post is purely an artifact of the &lt;code&gt;Future&lt;&#x2F;code&gt; trait’s design.&lt;&#x2F;p&gt;
&lt;p&gt;Having to choose between algorithmic complexity and allocations is also the
reason why I haven&#x27;t proposed to upstream futures-concurrency APIs to the stdlib
yet. The Rust stdlib has a design principle that disallows hidden allocations.
But at work we also know we need to guard against API misuse. That means we’re
likely going to hit cases where using the stdlib APIs are actually &lt;em&gt;not&lt;&#x2F;em&gt;
recommended. And it’s hard to justify upstreaming something we might immediately
want to guard against using.&lt;&#x2F;p&gt;
&lt;p&gt;This is also not the only problem with the &lt;code&gt;Future&lt;&#x2F;code&gt; trait design. I’ve spoken at
length about the problems the related &lt;code&gt;Pin&lt;&#x2F;code&gt; API has. And in this post I&#x27;ve also
touched on the &lt;code&gt;!Send&lt;&#x2F;code&gt; Waker problem. By my count the &lt;code&gt;Future&lt;&#x2F;code&gt; trait has seven
problems like this, which I’ll try to describe in future posts.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;This is not just a hypothetical - its an issue we’ve had at Microsoft. We can’t reasonably expect that every person implementing the future trait is an async expert. And so we need primitives which don’t just pass responsibility for performance to individual users.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;To be fair - probably about half that, since futures which have completed aren’t polled again.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;I hope I don’t have to explain that having &lt;code&gt;Send&lt;&#x2F;code&gt; expressed in the type system is a good thing.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</description>
        </item>
        <item>
            <title>Open and Closed Effect Systems</title>
            <pubDate>Thu, 22 May 2025 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/open-and-closed-effect-systems/</link>
            <guid>https://blog.yoshuawuyts.com/open-and-closed-effect-systems/</guid>
            <description>&lt;p&gt;When discussing effect systems in the context of production programming
languages, I believe that the most important distinction is whether effects are
purely defined by the language, or whether users are also able to define them.
When Magnus Madsen from the &lt;a href=&quot;https:&#x2F;&#x2F;flix.dev&quot;&gt;Flix programming language&lt;&#x2F;a&gt; joined
the Rust T-Lang call for two sessions last December, he used the terms “open”
and “closed” to describe this distinction:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Closed effect systems&lt;&#x2F;strong&gt;: are systems where all effects are all defined by
the language as built-ins. The number of effects may grow over time, but effects
are only ever defined by the language itself. This makes the number of possible
effects &lt;em&gt;bounded&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Open effect systems&lt;&#x2F;strong&gt;: allow users of the language to also define their own
control-flow effects, which exist alongside the language built-in effects. This
makes the number of possible effects &lt;em&gt;unbounded&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The most interesting effects in programming languages &lt;em&gt;have&lt;&#x2F;em&gt; to be built-in.
This includes things like controlling whether a function guarantees it will
terminate (“divergence”). Or whether a function is allowed to perform side
effects (“purity”).&lt;&#x2F;p&gt;
&lt;p&gt;This is different from user-defined effects. These are typically defined using
“algebraic effect handlers”, but I’ve also seen the term “typed continuation”
used &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. I think of these more or less as language-level support for
thoroughly typed iterators&#x2F;generators&#x2F;coroutines. It doesn’t really make sense
to express “divergence” using iterators. Which is why even though all effect
handlers are effects, not all effects are expressed using effect handlers.&lt;&#x2F;p&gt;
&lt;p&gt;In the context of Rust all we’re discussing right now is the introduction of a
&lt;em&gt;closed&lt;&#x2F;em&gt; effect system. And that’s not because we don’t think an open system
would not be useful or good. But because formalizing and generalizing Rust’s
effect system in a backwards-compatible way is an incredible amount of work
already. And in order to ship, we have to draw the line somewhere &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;I believe there is a difference between the two terms, but I don’t quite remember. I find “typed continuation” to be a lot more evocative though. Coming from Node.js 0.8, I think of this kind of as “what if all callbacks were fully typed and we had a compiler that ensured they were handled”. Maybe not syntactically the same, but I think it’s semantically quite close.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Though that doesn’t mean we can’t keep syntactic space open to consider it later. Just because we’re saying “not now” doesn’t mean we’re saying “not ever”.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</description>
        </item>
        <item>
            <title>Automatic interleaving of high-level concurrent operations</title>
            <pubDate>Mon, 05 May 2025 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/automatic-interleaving-of-high-level-concurrent-operations/</link>
            <guid>https://blog.yoshuawuyts.com/automatic-interleaving-of-high-level-concurrent-operations/</guid>
            <description>&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;When working with low-level concurrency (atomics), programming languages are
generally quite eager for compilers to reorder operations if it leads to better
performance. Information about whether it&#x27;s ok to reorder operations is encoded
using Atomic
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;sync&#x2F;atomic&#x2F;enum.Ordering.html&quot;&gt;Orderings&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;sync&#x2F;atomic&#x2F;fn.fence.html&quot;&gt;Fences&lt;&#x2F;a&gt;, and
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;sync&#x2F;atomic&#x2F;index.html&quot;&gt;Operations&lt;&#x2F;a&gt;. It&#x27;s strange
that most programming languages that support semantic-aware reordering of
low-level concurrent operations, don&#x27;t also include similar support for reordering the execution of high-level concurrent operations.&lt;&#x2F;p&gt;
&lt;p&gt;To my knowledge this is true for most languages, with the notable exception of
Swift and its &lt;code&gt;async let&lt;&#x2F;code&gt; construct. This feature preserves the linear-looking
nature of async code, but allows the compiler to inspect the control flow graph
and schedule operations concurrently where possible. That means that just like
with atomics, an operation that is defined later in a piece of code may finish
execution before an operation that appears earlier. Here is an example Swift
program where everything that &lt;em&gt;can&lt;&#x2F;em&gt; be concurrent actually &lt;em&gt;is&lt;&#x2F;em&gt; concurrent:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;swift&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-swift &quot;&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;func &lt;&#x2F;span&gt;&lt;span&gt;makeDinner() async throws -&amp;gt; Meal {
&lt;&#x2F;span&gt;&lt;span&gt;  async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; veggies = chopVegetables()                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 1. concurrent with: 2, 3
&lt;&#x2F;span&gt;&lt;span&gt;  async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; tofu = marinateTofu()                         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 2. concurrent with: 1, 3
&lt;&#x2F;span&gt;&lt;span&gt;  async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; oven = preheatOven(temperature: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;350&lt;&#x2F;span&gt;&lt;span&gt;)          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 3. concurrent with: 1, 2, 4
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; dish = Dish(ingredients: await [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;try&lt;&#x2F;span&gt;&lt;span&gt; veggies, tofu]) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 4. depends on: 1, 2, concurrent with: 3
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; await oven.cook(dish, duration: .hours(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;))       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 5. depends on: 3, 4, not concurrent
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;&#x2F;h2&gt;
&lt;p&gt;To me this represents the pinnacle of language-level support for
asynchronous&#x2F;concurrent programming. It makes it trivial to change any code that
&lt;em&gt;may&lt;&#x2F;em&gt; be run concurrently to actually run concurrently. It enables the compiler
to take care of what is otherwise tedious and&#x2F;or illegible. Take for example
this code that&#x27;s written in a serial fashion using async&#x2F;.await:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;make_dinner&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; SomeResult&amp;lt;Meal&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; veggies = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;chop_vegetables&lt;&#x2F;span&gt;&lt;span&gt;().await?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; tofu = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;marinate_tofu&lt;&#x2F;span&gt;&lt;span&gt;().await?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; oven = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;preheat_oven&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;350&lt;&#x2F;span&gt;&lt;span&gt;).await;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; dish = Dish(&amp;amp;[veggies, tofu]).await;
&lt;&#x2F;span&gt;&lt;span&gt;    oven.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;cook&lt;&#x2F;span&gt;&lt;span&gt;(dish, Duration::from_mins(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3 &lt;&#x2F;span&gt;&lt;span&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;60&lt;&#x2F;span&gt;&lt;span&gt;)).await
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using &lt;code&gt;Future::join&lt;&#x2F;code&gt; operations we can rewrite it to execute independent
operations concurrently. But this comes with the downside that the code is now
significantly less legible. Here is the same code, written using &lt;code&gt;Future::try_join&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_concurrency::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;make_dinner&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; SomeResult&amp;lt;Meal&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; dish_fut = {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; veggies_fut = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;chop_vegetables&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; tofu_fut = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;marinate_tofu&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(veggies, tofu) = (veggies_fut, tofu_fut).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_join&lt;&#x2F;span&gt;&lt;span&gt;().await?;
&lt;&#x2F;span&gt;&lt;span&gt;        Dish::new(&amp;amp;[veggies, tofu]).await
&lt;&#x2F;span&gt;&lt;span&gt;    };
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; oven_fut = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;preheat_oven&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;350&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(dish, oven) = (dish_fut, oven_fut).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_join&lt;&#x2F;span&gt;&lt;span&gt;().await?;
&lt;&#x2F;span&gt;&lt;span&gt;    oven.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;cook&lt;&#x2F;span&gt;&lt;span&gt;(dish, Duration::from_mins(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3 &lt;&#x2F;span&gt;&lt;span&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;60&lt;&#x2F;span&gt;&lt;span&gt;)).await
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;To capitalize on one of the core features of &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; (&lt;em&gt;ad-hoc concurrent
scheduling&lt;&#x2F;em&gt;), we had to sacrifice one of its main benefits (legibility).&lt;&#x2F;strong&gt; It&#x27;s
not good when two core parts of the same feature are in tension with each other
like that. And we can&#x27;t just wave a wand and tell the compiler to automatically
execute these futures concurrently. Futures tend to express operations that
change program state in one way or another. That is to say: most futures encode
&lt;em&gt;side-effects&lt;&#x2F;em&gt;. And the compiler can&#x27;t automatically infer which side effects
can be executed serially and which can be executed concurrently. That&#x27;s because
it&#x27;s not aware of the program &lt;em&gt;semantics&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-solution&quot;&gt;The Solution&lt;&#x2F;h2&gt;
&lt;p&gt;The solution is to allow programmers to provide opt-in to explicit reorderings
in their code, just like Swift does using &lt;code&gt;async let&lt;&#x2F;code&gt;. We could use a concise
notation along the lines of &lt;code&gt;.co.await&lt;&#x2F;code&gt; (this is a strawman, pick your own
favorite notation). We want the notation to be in postfix position because
unlike Swift we don&#x27;t want to eagerly start executing when operations are
defined, but only affect the way operations are scheduled when &lt;code&gt;.await&lt;&#x2F;code&gt;ed. And
this way we never have to actually have to represent it in the type system
either &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#assumption&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. This would look something like this:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;assumption&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Writing &lt;code&gt;.co&lt;&#x2F;code&gt; without following it with an &lt;code&gt;.await&lt;&#x2F;code&gt; should be a compiler error. The &lt;code&gt;.co&lt;&#x2F;code&gt; would serve as a modifier on the &lt;code&gt;.await&lt;&#x2F;code&gt;. Though perhaps something like C++&#x27;s &lt;code&gt;co_await&lt;&#x2F;code&gt; notation is simpler. Whatever the syntax though, I don&#x27;t think it should ever surface to the type system.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;make_dinner&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; SomeResult&amp;lt;Meal&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; veggies = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;chop_vegetables&lt;&#x2F;span&gt;&lt;span&gt;().co.await?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; tofu = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;marinate_tofu&lt;&#x2F;span&gt;&lt;span&gt;().co.await?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; oven = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;preheat_oven&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;350&lt;&#x2F;span&gt;&lt;span&gt;).co.await;
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; dish = Dish(&amp;amp;[veggies, tofu]).co.await;
&lt;&#x2F;span&gt;&lt;span&gt;    oven.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;cook&lt;&#x2F;span&gt;&lt;span&gt;(dish, Duration::from_mins(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3 &lt;&#x2F;span&gt;&lt;span&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;60&lt;&#x2F;span&gt;&lt;span&gt;)).await
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This code would directly lower to the equivalent of the &lt;code&gt;Future::join&lt;&#x2F;code&gt;-based
scheme. But with the benefit of needing far less ceremony to encode the same
semantics. The other benefit of this scheme is that we always retain the option
to schedule these operations serially if we choose to. That makes this scheme
compatible with async-polymorphic functions, where manual &lt;code&gt;Future::join&lt;&#x2F;code&gt; calls
are not.&lt;&#x2F;p&gt;
&lt;p&gt;A feature along these lines is important, because in order to make full use of
async Rust&#x27;s concurrent scheduling capabilities, any operations which can be
executed concurrently should be executed concurrently. But without language
support that comes at a severe cost to legibility, and in turn maintainability.
The only way out of this dilemma is to do what Swift has done and directly
include language support for it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;further-reading&quot;&gt;Further Reading&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;tasks-are-the-wrong-abstraction&#x2F;&quot;&gt;Tasks are the Wrong Abstraction&lt;&#x2F;a&gt; - Introduces the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yoshuawuyts&#x2F;parallel-future&quot;&gt;&lt;code&gt;ParallelFuture&lt;&#x2F;code&gt; trait&lt;&#x2F;a&gt;, which can be combined with the scheme outlined in this post to automatically schedule futures on multiple cores.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;tree-structured-concurrency&#x2F;&quot;&gt;Tree-Structured Concurrency&lt;&#x2F;a&gt; - Discusses what structured concurrency is, how to reason about it, and what&#x27;s missing for Rust to fully support it.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;extending-rusts-effect-system&#x2F;&quot;&gt;Extending Rust&#x27;s Effect System&lt;&#x2F;a&gt; - Discusses among other things async-polymorphic functions.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
        </item>
        <item>
            <title>Syntactic musings on match expressions</title>
            <pubDate>Tue, 29 Apr 2025 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/syntactic-musings-on-match-expressions/</link>
            <guid>https://blog.yoshuawuyts.com/syntactic-musings-on-match-expressions/</guid>
            <description>&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;One of the things that stands out to me is how similar &lt;code&gt;match&lt;&#x2F;code&gt; and &lt;code&gt;if..else&lt;&#x2F;code&gt;
are &lt;em&gt;semantically&lt;&#x2F;em&gt;, while being diverging a fair bit &lt;em&gt;syntactically&lt;&#x2F;em&gt;. The reasons for that seem mostly accidental, and I have a sneaking suspicion we could make things a little easier by making both constructs look more similar.&lt;&#x2F;p&gt;
&lt;p&gt;In this post I&#x27;ll be showing some control flow examples based on a queue that can either be online of offline. This is defined by an enum &lt;code&gt;QueueState&lt;&#x2F;code&gt; which stores the length of the queue as a u32:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;QueueState {
&lt;&#x2F;span&gt;&lt;span&gt;    Online(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    Offline(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Depending on whether the queue is actively having new data added to it (online),
we will want to reason differently about the queue&#x27;s limits (&lt;code&gt;u32&lt;&#x2F;code&gt;).  We also want to know
change the behavior based on whether the queue is full or not, and in order to
do that we will want to call a function:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span&gt;{ .. }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;logical-and&quot;&gt;Logical AND&lt;&#x2F;h2&gt;
&lt;p&gt;Take the humble &lt;code&gt;if&lt;&#x2F;code&gt;-guard. We can use this in &lt;code&gt;match&lt;&#x2F;code&gt; arms to chain
conditions, which is useful when we want to do something with a value contained
within a structure. Here the &lt;code&gt;is_full&lt;&#x2F;code&gt; method returns a bool. But in order to
call it we have first access the number contained in the &lt;code&gt;Online&lt;&#x2F;code&gt; variant:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; state {
&lt;&#x2F;span&gt;&lt;span&gt;    QueueState::Online(count) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                        ^^^^^^^^^^^^^^^^^^
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                            if-guard
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is online and not full&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    _ =&amp;gt; println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is in an unknown state&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;),
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;if&lt;&#x2F;code&gt;-guards are really just a logical AND. In match statements we&#x27;re in the
process of adding &lt;code&gt;if let&lt;&#x2F;code&gt;-chaining to Rust by way of &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;pull&#x2F;2497&quot;&gt;RFC 2497&lt;&#x2F;a&gt; (stable in Rust 1.88). With that we&#x27;ll be able to write this same &lt;code&gt;match&lt;&#x2F;code&gt; condition as follows:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span&gt;QueueState::Online(count) = state &amp;amp;&amp;amp; !&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                                       ^^^^^^^^^^^^^^^^^^
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                                           &amp;amp;&amp;amp; chaining
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is online and not full&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is in an unknown state&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is basically the same feature exposed two different ways. Instead I really
would like to be able to use &lt;code&gt;&amp;amp;&amp;amp;&lt;&#x2F;code&gt; in both cases, bringing the two closer together:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; state {
&lt;&#x2F;span&gt;&lt;span&gt;    QueueState::Online(count) &amp;amp;&amp;amp; !&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                        ^^^^^^^^^^^^^^^^^^
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                            &amp;amp;&amp;amp; chaining
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is online and not full&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    _ =&amp;gt; println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is in an unknown state&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;),
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I can guarantee that just about everyone who has had exposure to a language
which C-like notation (which rounds to all programmers) will have little trouble
understanding how this works. &lt;code&gt;if&lt;&#x2F;code&gt;-guards, in comparison, tend to be harder to
intuit.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;logical-or&quot;&gt;Logical OR&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;blob&#x2F;master&#x2F;text&#x2F;3637-guard-patterns.md&quot;&gt;RFC 3637&lt;&#x2F;a&gt;
introduces the &quot;guard patterns&quot; feature: an extension to Rust&#x27;s pattern notation
which that moves &lt;code&gt;if&lt;&#x2F;code&gt; guards out of match expressions and into all patterns. What it functionally provides us with is a way
to chain boolean AND expressions with logical OR expressions in all patterns. Say we took our previous example, and we wanted to print
a message if &lt;code&gt;is_full&lt;&#x2F;code&gt; returned &lt;code&gt;false&lt;&#x2F;code&gt;, regardless of the whether the queue was
online or offline. Using chained &lt;code&gt;if..let&lt;&#x2F;code&gt;s we would write this as follows:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span&gt;QueueState::Online(count) = state &amp;amp;&amp;amp; !&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is online and not full&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else if let &lt;&#x2F;span&gt;&lt;span&gt;QueueState::Online(count) = state &amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is full&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 1. This statement...
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else if let &lt;&#x2F;span&gt;&lt;span&gt;QueueState::Offline(count) = state &amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is full&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 2. ...is duplicated here.
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is in an unknown state&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a little annoying because ideally we&#x27;d want both the second and third condition to be one big condition, separated by a logical &lt;code&gt;OR&lt;&#x2F;code&gt;. Guard patterns are the feature which will allow us to do exactly that by bringing &lt;code&gt;if&lt;&#x2F;code&gt;-guards and pattern OR-based pattern chaining to expressions. With that we would rewrite this as follows:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span&gt;QueueState::Online(count) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) = state {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                           ^^^^^^^^^^^^^^^^^^
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                           now using an if-guard, for fun
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is online and not full&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else if let &lt;&#x2F;span&gt;&lt;span&gt;((QueueState::Online(count) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) = state) | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; logical OR
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                   Either matches on pattern 1...
&lt;&#x2F;span&gt;&lt;span&gt;    (QueueState::Offline(count) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) = state)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                   ...or on pattern 2.
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is full&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; No more duplication!
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is in an unknown state&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There&#x27;s a lot going on here. For one, this makes &lt;code&gt;if&lt;&#x2F;code&gt;-guards legal in &lt;code&gt;if..let&lt;&#x2F;code&gt;
expressions. And it also allows multiple patterns to be placed used in a single
conditional using OR semantics, as long as they&#x27;re appropriately parenthesized.
Let&#x27;s keep going on, and use this with a &lt;code&gt;match&lt;&#x2F;code&gt; expression:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; state {
&lt;&#x2F;span&gt;&lt;span&gt;    QueueState::Online(count) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is online and not full&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    ((QueueState::Online(count) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count)) |
&lt;&#x2F;span&gt;&lt;span&gt;    (QueueState::Offline(count) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count)) =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is full&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; No more duplication!
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    _ =&amp;gt; println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is in an unknown state&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;),
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a lot better since the flow is clearer. By not having the explicit &lt;code&gt;= state&lt;&#x2F;code&gt; repeated on every line we can now actually read all the statements
left-to-right.  That&#x27;s all good. We like that. Porting from the &lt;code&gt;if..let&lt;&#x2F;code&gt;
version to the &lt;code&gt;match&lt;&#x2F;code&gt; version was also really easy. We didn&#x27;t have to change
the &lt;code&gt;if..let&lt;&#x2F;code&gt; conditions at all, aside from trimming their ends. That&#x27;s good!&lt;&#x2F;p&gt;
&lt;p&gt;What&#x27;s less good however is that we achieved this by making &lt;code&gt;if..else&lt;&#x2F;code&gt;
expressions more involved. The interaction of RFC 2497 &lt;code&gt;if..let&lt;&#x2F;code&gt; chains and RFC
3637 guard patterns seems particularly like it might catch people off guard.
Consider for example this line:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span&gt;Foo::Bar(x) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;cond&lt;&#x2F;span&gt;&lt;span&gt;(x) = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span&gt;() &amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;Bin::Baz = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;baz&lt;&#x2F;span&gt;&lt;span&gt;() { .. }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The order in which expressions are evaluated on this line is here is
&lt;code&gt;2-3-1-5-4&lt;&#x2F;code&gt;. That means it&#x27;s probably not advisable to mix both features. The
reason why these interactions are this way is &lt;strong&gt;because both RFCs operate from
fundamentally opposing premises:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;RFC 2497&lt;&#x2F;strong&gt; believes we should enable boolean operators like &lt;code&gt;&amp;amp;&amp;amp;&lt;&#x2F;code&gt; to work in more places.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;RFC 3637&lt;&#x2F;strong&gt; believes we should enable match-specific operators like &lt;code&gt;if&lt;&#x2F;code&gt;-guards work in more places.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In the previous section we already looked at replacing &lt;code&gt;if&lt;&#x2F;code&gt;-guards with the &lt;code&gt;&amp;amp;&amp;amp;&lt;&#x2F;code&gt;
operator, inspired by &lt;code&gt;if..let&lt;&#x2F;code&gt;-chaining. It&#x27;s not a far reach to imagine &lt;code&gt;if..let&lt;&#x2F;code&gt;-chaining using the &lt;code&gt;||&lt;&#x2F;code&gt; operator as well. That would look something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span&gt;QueueState::Online(count) = state &amp;amp;&amp;amp; !&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                                   ^^^^^^^^^^^^^^^^^^
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                                   if-let chain
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is online and not full&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else if let &lt;&#x2F;span&gt;&lt;span&gt;QueueState::Online(count) = state &amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) ||
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                   Either matches on pattern 1...
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;QueueState::Offline(count) = state &amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                   ...or on pattern 2.
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is full&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; No more duplication!
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is in an unknown state&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s the same functionality as before, but provided as a natural extension to
&lt;code&gt;&amp;amp;&amp;amp;&lt;&#x2F;code&gt;-based &lt;code&gt;if..let&lt;&#x2F;code&gt;-chaining. Now once more, let&#x27;s try rewriting this as a
&lt;code&gt;match&lt;&#x2F;code&gt; expression:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; state {
&lt;&#x2F;span&gt;&lt;span&gt;    QueueState::Online(count) &amp;amp;&amp;amp; !&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is online and not full&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    QueueState::Online(count) &amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) || &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; &amp;lt;- logical OR!
&lt;&#x2F;span&gt;&lt;span&gt;    QueueState::Offline(count) &amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is full&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    _ =&amp;gt; println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is in an unknown state&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;),
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What&#x27;s neat here is that because logical  AND (&lt;code&gt;&amp;amp;&amp;amp;&lt;&#x2F;code&gt;) takes precedence over
logical OR (&lt;code&gt;||&lt;&#x2F;code&gt;)
(&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;reference&#x2F;expressions.html#r-expr.precedence&quot;&gt;ref&lt;&#x2F;a&gt;),
we don&#x27;t need to resort to wrapping our patterns in order to chain them. Oh and
I guess of course it&#x27;s also nice that just about every programmer regardless of
familiarity with Rust should be able to parse what is going on here.&lt;&#x2F;p&gt;
&lt;p&gt;But even more than that: look at this! This is code that I want to be writing.
It&#x27;s not trying to be clever or inventing anything particular new. It&#x27;s defining
feature is just how ordinary this looks. And that really agrees with my
sensibilities for what a general-purpose programming language should feel like.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;if-let-evaluation-ordering&quot;&gt;&lt;code&gt;if let&lt;&#x2F;code&gt;-evaluation ordering&lt;&#x2F;h2&gt;
&lt;p&gt;I don&#x27;t like reading &lt;code&gt;if-let&lt;&#x2F;code&gt; statements because they flip the read order from
right-to-left. I double don&#x27;t like reading &lt;code&gt;if-let&lt;&#x2F;code&gt; statements when chained
because they need to be read center-left-right. I like the &lt;code&gt;is&lt;&#x2F;code&gt;-operator because
it allows us to fix that. Let me show you how by taking our last &lt;code&gt;if let..else&lt;&#x2F;code&gt;
example, with all comments stripped:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span&gt;QueueState::Online(count) = state &amp;amp;&amp;amp; !&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is online and not full&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else if let &lt;&#x2F;span&gt;&lt;span&gt;QueueState::Online(count) = state &amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) || 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;QueueState::Offline(count) = state &amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count)
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is full&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is in an unknown state&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However much I like the boolean operators here, I don&#x27;t like the order in which
statements evaluate. The first line in our example above is evaluated as follows:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span&gt;QueueState::Online(cond) = state &amp;amp;&amp;amp; !&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) { .. }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;     ^^^^^^^^^^^^^^^^^^^^^^^^   ^^^^^    ^^^^^^^^^^^^^^^
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                |                 |              |
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                |       this is evaluated first  |
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                |                                |
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;     this is evaluated second                    |
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                                                 |
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                                        this is evaluated last
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;joshtriplett&#x2F;rfcs&#x2F;blob&#x2F;is&#x2F;text&#x2F;3573-is.md&quot;&gt;RFC 3573&lt;&#x2F;a&gt;
proposes to add the &lt;code&gt;is&lt;&#x2F;code&gt;-operator to the language, inspired by C#&#x27;s feature of
the same name. This would fix the evaluation order, making the same code instead
read from top-to-bottom, right-to-left:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; state is QueueState::Online(count) &amp;amp;&amp;amp; !&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is online and not full&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else if&lt;&#x2F;span&gt;&lt;span&gt; state is QueueState::Online(count) &amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) || 
&lt;&#x2F;span&gt;&lt;span&gt;    state is QueueState::Offline(count) &amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count)
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is full&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is in an unknown state&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To me this is Rust as it should be. The point has always been to make a language
that is as practical as possible to use, without compromising on correctness,
performance, and control. Making evaluation orders easier to follow seems like
it&#x27;s right in line with that goal. Here is that same line annotated, but using the &lt;code&gt;is&lt;&#x2F;code&gt; notation:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; state is QueueState::Online(cond) &amp;amp;&amp;amp; !&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) { .. }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ^^^^^    ^^^^^^^^^^^^^^^^^^^^^^^^    ^^^^^^^^^^^^^^^
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;   |                         |                |
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;  this is evaluated first    |                |        
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                             |                |
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                  this is evaluated second    |
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                                              |
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                                    this is evaluated last
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It also comes with an added benefit: it makes it so refactoring code from
&lt;code&gt;if..else&lt;&#x2F;code&gt; form to &lt;code&gt;match&lt;&#x2F;code&gt; form produces an incredibly small diff. It&#x27;s mostly
the same code, but with the start of each condition trimmed:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; state {
&lt;&#x2F;span&gt;&lt;span&gt;    QueueState::Online(count) &amp;amp;&amp;amp; !&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is online and not full&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    QueueState::Online(count) &amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) ||
&lt;&#x2F;span&gt;&lt;span&gt;    QueueState::Offline(count) &amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_full&lt;&#x2F;span&gt;&lt;span&gt;(count) =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is full&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    _ =&amp;gt; println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;queue is in an unknown state&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;),
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This would make it possible to explain conditional control flow more
incrementally. I see the potential for carving out a little didactic staircase
into Rust&#x27;s famously steep learning curve that goes a little something like
this:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Start by introducing &lt;code&gt;if..else&lt;&#x2F;code&gt;, which most programmers will already know.&lt;&#x2F;li&gt;
&lt;li&gt;Then introduce &lt;code&gt;is&lt;&#x2F;code&gt; as a more powerful version of &lt;code&gt;typeof&lt;&#x2F;code&gt; in other languages.&lt;&#x2F;li&gt;
&lt;li&gt;Finally introduce &lt;code&gt;match&lt;&#x2F;code&gt; as a more ergonomic version of &lt;code&gt;if..else&lt;&#x2F;code&gt; + &lt;code&gt;is&lt;&#x2F;code&gt;. Like &lt;code&gt;switch&lt;&#x2F;code&gt; in other languages, but exhaustively checking all cases.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;We never take any concepts away or have big changes in notation. Each concept
neatly builds on the previous one, and we don&#x27;t need to wait to introduce &lt;code&gt;if&lt;&#x2F;code&gt;-let until much later &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;book&#x2F;ch19-03-pattern-syntax.html#extra-conditionals-with-match-guards&quot;&gt;like we do now&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;closing-words&quot;&gt;Closing Words&lt;&#x2F;h2&gt;
&lt;p&gt;Another thing I wasn&#x27;t quite sure when to talk about when it comes to the guard
patterns RFC is its interaction with pattern types. Bringing &lt;code&gt;if&lt;&#x2F;code&gt;-guards into
pattern feels like it changes the pattern notation from a fairly
tractable&#x2F;limited subset that we can evaluate in reasonable time into a system
for arbitrary pre&#x2F;post-conditions. Unless of course we disallow those kinds of
patterns in pattern types - which creates diverging pattern notations.&lt;&#x2F;p&gt;
&lt;p&gt;Overall I feel like we have a lot to gain in the language by making &lt;code&gt;match&lt;&#x2F;code&gt;-expressions
feel more consistent with the rest of the conditional expressions. After writing
the bulk of this post, I remembered that what I&#x27;m sharing here is actually not a
unique insight. &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jhpratt&#x2F;rfcs&#x2F;blob&#x2F;cfg-logical-ops&#x2F;text&#x2F;0000-cfg-logical-ops.md&quot;&gt;RFC
3796&lt;&#x2F;a&gt;
&lt;code&gt;cfg_logical_ops&lt;&#x2F;code&gt; by Jacob Pratt proposes the addition of the boolean &lt;code&gt;&amp;amp;&amp;amp;&lt;&#x2F;code&gt;,
&lt;code&gt;||&lt;&#x2F;code&gt;, and &lt;code&gt;!&lt;&#x2F;code&gt; operators in &lt;code&gt;cfg&lt;&#x2F;code&gt; attributes. Effectively replacing the existing
domain-specific &lt;code&gt;all()&lt;&#x2F;code&gt;, &lt;code&gt;any()&lt;&#x2F;code&gt;, and &lt;code&gt;not()&lt;&#x2F;code&gt; operators.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; current
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cfg&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;all&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;any&lt;&#x2F;span&gt;&lt;span&gt;(a, b), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;any&lt;&#x2F;span&gt;&lt;span&gt;(c, d), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;not&lt;&#x2F;span&gt;&lt;span&gt;(e)))]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;MyStruct {}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; proposed
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cfg&lt;&#x2F;span&gt;&lt;span&gt;((a || b) &amp;amp;&amp;amp; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt; || &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;d&lt;&#x2F;span&gt;&lt;span&gt;) &amp;amp;&amp;amp; !&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;e&lt;&#x2F;span&gt;&lt;span&gt;)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;MyStruct {}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I like what that RFC proposes. I doubly like it when we consider it as part of a
broader effort to reduce the amount of
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;pull&#x2F;3796#issuecomment-2800330037&quot;&gt;micro-syntaxes&lt;&#x2F;a&gt;
spread throughout the language. In turn making Rust an easier language, by
virtue of it being smaller and more consistent.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Syntactic Musings on View Types</title>
            <pubDate>Fri, 04 Apr 2025 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/syntactic-musings-on-view-types/</link>
            <guid>https://blog.yoshuawuyts.com/syntactic-musings-on-view-types/</guid>
            <description>&lt;p&gt;Here&#x27;s a silly little insight I had the other day: if you squint, both View
Types and Pattern Types seem like lightweight forms of Refinement Types &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.
Both will enable constraining types, but in slightly different and complementary
ways. Let&#x27;s take a look at this using an example of an RGB struct containing
fields for individual Red, Green, and Blue channels stored as &lt;code&gt;usize&lt;&#x2F;code&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;I like the term &quot;lightweight refinement types&quot; for the category of extensions that include pattern types and view types. To me it&#x27;s reminiscent of &lt;em&gt;lightweight formal methods&lt;&#x2F;em&gt;: less thorough than the full thing, but with incredible returns for the relative effort expended.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Don&#x27;t question why we&#x27;re storing these values as &lt;code&gt;usize&lt;&#x2F;code&gt; too much. It&#x27;s a little silly. For the purpose of this example just pretend there is some reason why we have to do it like this.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Debug, Default)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Rgb {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;g&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Pattern types will give us the ability to directly use things like ranges or
enum members in type signatures. In the following example the type &lt;code&gt;usize&lt;&#x2F;code&gt; is
&lt;em&gt;refined&lt;&#x2F;em&gt; to statically only be allowed to contain values between &lt;code&gt;0..255&lt;&#x2F;code&gt;. This
is similar to the &lt;code&gt;NonZero*&lt;&#x2F;code&gt; types in the stdlib, but as part of the language
and usable with arbitrary patterns:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Rgb {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;set_red&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;num&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt; is ..255) { .. }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                                   ^^^^^^^^ range pattern
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;View types are about segmenting the fields contained in &lt;code&gt;self&lt;&#x2F;code&gt; so that multiple
(mutable) methods can operate on the same type without resulting in borrow
checking issues. In the following example we provide mutable access to
individual fields using separate methods. None of these methods take overlapping
borrows of the fields in &lt;code&gt;Self&lt;&#x2F;code&gt;. This means we&#x27;re free to call all of these
methods, observe their return types, and we won&#x27;t get any borrow checker errors.
Here&#x27;s an example using the syntax from &lt;a href=&quot;https:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2025&#x2F;02&#x2F;25&#x2F;view-types-redux&#x2F;&quot;&gt;Niko&#x27;s latest
post&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Rgb {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;red_mut&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; { r } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; .. { .. }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                    ^^^^^ view
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;green_mut&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; { g } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; .. { .. }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                      ^^^^^ view
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;blue_mut&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; { b } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; .. { .. }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                     ^^^^^ view
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here&#x27;s a fun question: what happens if we combine combine Pattern Types and View
Types? Both serve different purposes, and I know I&#x27;ve got cases where I&#x27;d like
to combine them. So what would that look like? In the abstract, it seems like we
would end up with something like the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Rgb {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; { r, g } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt; is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt; { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span&gt;: ..255, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;g&lt;&#x2F;span&gt;&lt;span&gt;: ..255, .. }) {}
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                ^^^^^^^^      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                  view                      pattern
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To me that seems like a lot to read. But also rather... double? Both View Types
and Pattern Types refine &lt;code&gt;Self&lt;&#x2F;code&gt; here. I would have expected us to be able to
combine both. Now what if View Types and Pattern Types instead shared the same
syntactic position. There&#x27;s a reason View Types have to use &lt;code&gt;is&lt;&#x2F;code&gt;, so let&#x27;s use
that. With that we could rewrite our earlier example like this instead:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Rgb {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt; is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt; { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span&gt;: ..255, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;g&lt;&#x2F;span&gt;&lt;span&gt;: ..255, .. }) {}
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                          view + pattern
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This seems a lot more readable to me. Combining both features seems much less like a hassle here, and maybe even… nice?
This updated notation would also affect our earlier View Types example. Using
the updated notation would now be written the same way, but without using any
patterns:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Rgb {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;red_mut&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt; is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt; { r, .. }) -&amp;gt; .. { .. }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                           ^^^^^^^^^ view
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;green_mut&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt; is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt; { g, .. }) -&amp;gt; .. { .. }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                             ^^^^^^^^^ view
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;blue_mut&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt; is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt; { b, .. }) -&amp;gt; .. { .. }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                            ^^^^^^^^^ view
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I feel like this would rather neatly unify where we talk about &lt;em&gt;refinements&lt;&#x2F;em&gt; in
function signatures. Notationally this reframes View Types as Pattern Types with ignored fields. Though we don&#x27;t necessarily need to adopt this notation: what I care about most is that we
think about how both features are intended to come together in the language to
create a cohesive experience. Thanks for reading!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>A survey of every iterator variant</title>
            <pubDate>Wed, 12 Feb 2025 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/a-survey-of-every-iterator-variant/</link>
            <guid>https://blog.yoshuawuyts.com/a-survey-of-every-iterator-variant/</guid>
            <description>&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Oh yeah, you like iterators? Name all of them. —&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I&#x27;m increasingly of the belief that before we can meaningfully discuss the
solution space, we have to first make an effort to build consensus on the
problem space. It&#x27;s hard to plan for a journey together if we don&#x27;t know what
the trip will be like along the way. Or worse: if we don&#x27;t agree in advance
where we want the journey to take us.&lt;&#x2F;p&gt;
&lt;p&gt;In Rust the &lt;code&gt;Iterator&lt;&#x2F;code&gt; trait is the single-most complex trait in the stdlib. It
provides 76 methods, and by my estimate (I stopped counting at 120) has around
150 trait implementations in the stdlib alone. It also features a broad range of
extension traits like &lt;code&gt;FusedIterator&lt;&#x2F;code&gt; and &lt;code&gt;ExactSizeIterator&lt;&#x2F;code&gt; that provide
additional capabilities. And it is itself a trait-based expression of one of
Rust&#x27;s core control-flow effects; meaning it is at the heart of a lot of
interesting questions about how we combine such effects.&lt;&#x2F;p&gt;
&lt;p&gt;Despite all that we know the &lt;code&gt;Iterator&lt;&#x2F;code&gt; trait falls short today and we would
like to extend it to do &lt;em&gt;more&lt;&#x2F;em&gt;. Async iteration is one popular capability people
are missing as a built-in. Another is the ability to author address-sensitive
(self-referential) iterators. Less in the zeitgeist but equally important are
iterators that can lend items with a lifetime, conditionally terminate
early, and take external arguments on each call to &lt;code&gt;next&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m writing this post to enumerate all of the iterator variants in use in Rust
today. So that we can scope the problem space to account for all of them. I&#x27;m
also doing this because I&#x27;ve started hearing talk about potentially
(soft-)deprecating &lt;code&gt;Iterator&lt;&#x2F;code&gt;. I believe we only get one shot at running such a
deprecation &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#nodejs&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, and if we are going to do one we need to make sure it&#x27;s a
solution that will plausibly get us through all of our known limitations. Not just one or two.&lt;&#x2F;p&gt;
&lt;p&gt;So without further ado: let&#x27;s enumerate every variation of the existing
&lt;code&gt;Iterator&lt;&#x2F;code&gt; trait we know we want to write, and discuss how those variants
interact with each other to create interesting new kinds of iterators.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;nodejs&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;I&#x27;m basing this off of my experience being a part of the Node.js Streams WG through the mid-2010s. By my count Node.js now features five distinct generations of stream abstractions. Unsurprisingly it&#x27;s not particularly pleasant to use, and ideally something we should avoid replicating in Rust. Though I&#x27;m not opposed to running deprecations of core traits in Rust either, I believe that in order to do that we want to be approaching 100% certainty that it&#x27;ll be the last deprecation we do. If we&#x27;re going to embark on a decade plus of migration issues, we have to make absolutely sure it&#x27;s worth it.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;base-iterator&quot;&gt;Base Iterator&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;Iterator&lt;&#x2F;code&gt; is a trait representing the stateful component of iteration;
&lt;code&gt;IntoIterator&lt;&#x2F;code&gt; represents the capability for a type to be iterated over. Here is
the &lt;code&gt;Iterator&lt;&#x2F;code&gt; trait as found in the stdlib today. The &lt;code&gt;Iterator&lt;&#x2F;code&gt; and
&lt;code&gt;IntoIterator&lt;&#x2F;code&gt; traits are closely linked, so throughout this post we will show
both to paint a more complete picture.&lt;&#x2F;p&gt;
&lt;p&gt;Throughout this post we will be covering variations on &lt;code&gt;Iterator&lt;&#x2F;code&gt; which provide
new capabilities. This trait is represents the absence of those capabilities: it
is blocking, cannot be evaluated during compilation, is strictly sequential, and
so on. Here is what the foundation of the &lt;code&gt;core::iter&lt;&#x2F;code&gt; submodule looks like today:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; An iterable type.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;IntoIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The type of elements yielded from the iterator.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Which kind of iterator are we turning this into?
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;IntoIter: Iterator&amp;lt;Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Returns an iterator over the elements in this type.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;IntoIter;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A type that yields values, one at the time.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Iterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The type of elements yielded from the iterator.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Advances the iterator and yields the next value.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Returns the bounds on the remaining length of the iterator.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;size_hint&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;, Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) { .. }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While not strictly necessary: the associated &lt;code&gt;IntoIterator::Item&lt;&#x2F;code&gt; type exists
for convenience. That way people using the trait can directly specify the &lt;code&gt;Item&lt;&#x2F;code&gt;
using &lt;code&gt;impl IntoIterator&amp;lt;Item = Foo&amp;gt;&lt;&#x2F;code&gt;, which is a lot more convenient than &lt;code&gt;I: &amp;lt;IntoIterator::IntoIterator as Iterator&amp;gt;::Item&lt;&#x2F;code&gt;, etc.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bounded-iterator&quot;&gt;Bounded Iterator&lt;&#x2F;h2&gt;
&lt;p&gt;The base &lt;code&gt;Iterator&lt;&#x2F;code&gt; trait represents a potentially infinite (unbounded) sequence
of items. It has a &lt;code&gt;size_hint&lt;&#x2F;code&gt; method that returns how many items the iterator
still expects to yield. That value is however not guaranteed to be correct, and is
intended to be used for optimizations only. From the docs:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Implementation notes&lt;&#x2F;strong&gt;
It is not enforced that an iterator implementation yields the declared number of elements. A buggy iterator may yield less than the lower bound or more than the upper bound of elements.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;size_hint()&lt;&#x2F;code&gt; is primarily intended to be used for optimizations such as reserving space for the elements of the iterator, but must not be trusted to e.g., omit bounds checks in unsafe code. An incorrect implementation of &lt;code&gt;size_hint()&lt;&#x2F;code&gt; should not lead to memory safety violations.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The Rust stdlib provides two &lt;code&gt;Iterator&lt;&#x2F;code&gt; subtraits that allow it to guarantee it
is bounded: &lt;code&gt;ExactSizeIterator&lt;&#x2F;code&gt; (stable) and &lt;code&gt;TrustedLen&lt;&#x2F;code&gt; (unstable). Both
traits take &lt;code&gt;: Iterator&lt;&#x2F;code&gt; as its super-trait bound and on its surface seem nearly
identical. But there is one key difference: &lt;code&gt;TrustedLen&lt;&#x2F;code&gt; is unsafe to implement allowing it to be used to guarantee safety invariants.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; An iterator that knows its exact length.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;ExactSizeIterator: Iterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Returns the exact remaining length of the iterator.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;{ .. }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Returns `true` if the iterator is empty.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;is_empty&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span&gt;{ .. }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; An iterator that reports an accurate length using `size_hint`.
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;unstable&lt;&#x2F;span&gt;&lt;span&gt;(feature = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;trusted_len&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub unsafe trait &lt;&#x2F;span&gt;&lt;span&gt;TrustedLen: Iterator {}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;ExactSizeIterator&lt;&#x2F;code&gt; has the same memory-safety guarantees as
&lt;code&gt;Iterator::size_hint&lt;&#x2F;code&gt; meaning: you can&#x27;t rely on it to be correct. That means
that if you&#x27;re say, collecting items from an iterator into a vec, you can&#x27;t omit bounds
checks and use &lt;code&gt;ExactSizeIterator::len&lt;&#x2F;code&gt; as the input to
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;vec&#x2F;struct.Vec.html#method.set_len&quot;&gt;&lt;code&gt;Vec::set_len&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
However if &lt;code&gt;TrustedLen&lt;&#x2F;code&gt; is implemented bounds checks can be omitted, since the
value returned by &lt;code&gt;size_hint&lt;&#x2F;code&gt; is now a safety invariant of the iterator.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fused-iterator&quot;&gt;Fused Iterator&lt;&#x2F;h2&gt;
&lt;p&gt;When working with an iterator, we typically iterate over items until the
iterator yields &lt;code&gt;None&lt;&#x2F;code&gt; at which point we treat the iterator as &quot;done&quot;. However the documentation for &lt;code&gt;Iterator::next&lt;&#x2F;code&gt; includes the following:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Returns &lt;code&gt;None&lt;&#x2F;code&gt; when iteration is finished. Individual iterator implementations may choose to resume iteration, and so calling &lt;code&gt;next()&lt;&#x2F;code&gt; again may or may not eventually start returning &lt;code&gt;Some(Item)&lt;&#x2F;code&gt; again at some point.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It&#x27;s rare to work with iterators which yield &lt;code&gt;None&lt;&#x2F;code&gt; and then resume again
afterwards, but the iterator trait explicitly allows it. Just like it allows for
an iterator to panic if &lt;code&gt;next&lt;&#x2F;code&gt; is called again after &lt;code&gt;None&lt;&#x2F;code&gt; has been yielded
once. Luckily the &lt;code&gt;FusedIterator&lt;&#x2F;code&gt; subtrait exists, which guarantees that once
&lt;code&gt;None&lt;&#x2F;code&gt; has been yielded once from an iterator, all future calls to &lt;code&gt;next&lt;&#x2F;code&gt; will
continue to yield &lt;code&gt;None&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; An iterator that always continues to yield `None` when exhausted.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;FusedIterator: Iterator {}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Most iterators in the stdlib implement &lt;code&gt;FusedIterator&lt;&#x2F;code&gt;. For iterators which
aren&#x27;t fused, it&#x27;s possible to call the &lt;code&gt;Iterator::fuse&lt;&#x2F;code&gt; combinator. The stdlib
docs recommend never taking a &lt;code&gt;FusedIterator&lt;&#x2F;code&gt; bound, instead favoring &lt;code&gt;Iterator&lt;&#x2F;code&gt;
in bounds and calling &lt;code&gt;fuse&lt;&#x2F;code&gt; to guarantee the fused behavior. For iterators that
already implement &lt;code&gt;FusedIterator&lt;&#x2F;code&gt; this is considered a no-op.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;FusedIterator&lt;&#x2F;code&gt; design works because
&lt;code&gt;Option::None&lt;&#x2F;code&gt; is &lt;em&gt;idempotent&lt;&#x2F;em&gt;: there is never a scenario where we can&#x27;t create a
new instance of &lt;code&gt;None&lt;&#x2F;code&gt;. Contrast this with enums such as
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;task&#x2F;enum.Poll.html&quot;&gt;&lt;code&gt;Poll&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; that lack a &quot;done&quot;
state -  and you see ecosystem traits such as
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;latest&#x2F;futures&#x2F;future&#x2F;trait.FusedFuture.html&quot;&gt;&lt;code&gt;FusedFuture&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
attempting to add this lack of expressivity back through other means. The need
for an idempotent &quot;done&quot; state will be important to keep in mind as we explore
other iterator variants throughout this post.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;thread-safe-iterator&quot;&gt;Thread-Safe Iterator&lt;&#x2F;h2&gt;
&lt;p&gt;Where bounded and fused iterators can be obtained by refining the &lt;code&gt;Iterator&lt;&#x2F;code&gt;
trait using subtraits, thread-safe iterators are obtained by composing the
&lt;code&gt;Send&lt;&#x2F;code&gt; and &lt;code&gt;Sync&lt;&#x2F;code&gt; auto-traits with the &lt;code&gt;Iterator&lt;&#x2F;code&gt; trait. That means there is no
need for dedicated &lt;code&gt;SendIterator&lt;&#x2F;code&gt; or &lt;code&gt;SyncIterator&lt;&#x2F;code&gt; traits. A &quot;thread-safe
iterator&quot; becomes a composition of &lt;code&gt;Iterator&lt;&#x2F;code&gt; and &lt;code&gt;Send&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;Sync&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Manual `Iterator` impl
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Iterator &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Cat { .. }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; These impls are implied by `Send`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; and `Sync` being auto-traits
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe impl &lt;&#x2F;span&gt;&lt;span&gt;Send &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Cat {}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe impl &lt;&#x2F;span&gt;&lt;span&gt;Sync &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Cat {}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And when taking impls in bounds, we can again express our intent by composing
traits in bounds. I&#x27;ve made the argument before that taking &lt;code&gt;Iterator&lt;&#x2F;code&gt; directly
in bounds is rarely what people actually want, so the bound would end up looking
like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;thread_safe_sink&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;: impl IntoIterator + Send) { .. }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we also want the individual items yielded by the iterator to be marked
thread-safe, we have to add additional bounds:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;thread_safe_sink&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;I&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;: I)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    I: IntoIterator&amp;lt;Item: Send&amp;gt; + Send,
&lt;&#x2F;span&gt;&lt;span&gt;{ .. }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While there is no lack of expressivity here, at times bounds like these can get
rather verbose. That should not be taken as indictment of the system itself, but
rather as a challenge to improve the ergonomics for the most common cases.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;dyn-compatible-iterator&quot;&gt;Dyn-Compatible Iterator&lt;&#x2F;h2&gt;
&lt;p&gt;Dyn-compatibility is another axis that traits are divided on. Unlike e.g.
thread-safety, dyn-compatibility is an inherent part of the trait and is
governed by &lt;code&gt;Sized&lt;&#x2F;code&gt; bounds. Luckily  both the &lt;code&gt;Iterator&lt;&#x2F;code&gt; and &lt;code&gt;IntoIterator&lt;&#x2F;code&gt;
traits are inherently dyn-compatible. That means they can be used to create
trait objects using the &lt;code&gt;dyn&lt;&#x2F;code&gt; keyword:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Iterator &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Cat { .. }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cat = Cat {};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; dyn_cat: &amp;amp;dyn Iterator = &amp;amp;cat; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ok
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are some iterator combinators such as
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.Iterator.html#method.count&quot;&gt;&lt;code&gt;count&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
that take an additional &lt;code&gt;Self: Sized&lt;&#x2F;code&gt; bound &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#dyn-limits&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. But because trait objects are
themselves sized, it all mostly works as expected:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;dyn-limits&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Admittedly my knowledge of &lt;code&gt;dyn&lt;&#x2F;code&gt; is spotty at best. Out of everything in this post, the section on &lt;code&gt;dyn&lt;&#x2F;code&gt; was the bit I had the least intuition about.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; cat = Cat {};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; dyn_cat: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; dyn Iterator = &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; cat;
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(dyn_cat.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;count&lt;&#x2F;span&gt;&lt;span&gt;(), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ok
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;double-ended-iterator&quot;&gt;Double-Ended Iterator&lt;&#x2F;h2&gt;
&lt;p&gt;Often times iterators over collections hold all data in memory, and can be
traversed in either direction. For this purpose Rust provides the
&lt;code&gt;DoubleEndedIterator&lt;&#x2F;code&gt; trait. Where &lt;code&gt;Iterator&lt;&#x2F;code&gt; builds on the &lt;code&gt;next&lt;&#x2F;code&gt; method,
&lt;code&gt;DoubleEndedIterator&lt;&#x2F;code&gt; builds on a &lt;code&gt;next_back&lt;&#x2F;code&gt; method. This allows items to be
taken from both the logical start and end of the iterator. And once both cursors
meet, iteration is considered over.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; An iterator able to yield elements from both ends.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;DoubleEndedIterator: Iterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Removes and  an element from the end of the iterator.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next_back&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While you&#x27;d expect this trait to be implemented for e.g. &lt;code&gt;VecDeque&lt;&#x2F;code&gt;, it&#x27;s
interesting to note that it&#x27;s also implemented for &lt;code&gt;Vec&lt;&#x2F;code&gt;, &lt;code&gt;String&lt;&#x2F;code&gt;, and other
collections that only grow in one direction. Also unlike some of the other
iterator refinements we&#x27;ve seen, &lt;code&gt;DoubleEndedIterator&lt;&#x2F;code&gt; has a required method
that is used as the basis for several new methods such as
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.DoubleEndedIterator.html#method.rfold&quot;&gt;&lt;code&gt;rfold&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
(reverse &lt;code&gt;fold&lt;&#x2F;code&gt;) and
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.DoubleEndedIterator.html#method.rfind&quot;&gt;&lt;code&gt;rfind&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
(reverse &lt;code&gt;find&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;seeking-iterator&quot;&gt;Seeking Iterator&lt;&#x2F;h2&gt;
&lt;p&gt;Both the &lt;code&gt;Iterator&lt;&#x2F;code&gt; and &lt;code&gt;Read&lt;&#x2F;code&gt;traits in Rust provide abstractions for streaming
iteration. The main difference is that &lt;code&gt;Iterator&lt;&#x2F;code&gt; works by returning arbitrary
owned types when calling &lt;code&gt;next&lt;&#x2F;code&gt;, where &lt;code&gt;Read&lt;&#x2F;code&gt; is limited to reading bytes into
buffers. But both abstractions keep a cursor that keeps track of which data has
been processed already, and which data still needs processing.&lt;&#x2F;p&gt;
&lt;p&gt;But not all streams are created equally. When we read data from a regular file &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#regular&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
on disk we can be sure that, as long as no writes occurred, we can read the same
file again and get the same output. That same guarantee is however not true for
sockets, where once we&#x27;ve read data from it we can&#x27;t read that same data again.
In Rust this distinction is surfaced via the &lt;code&gt;Seek&lt;&#x2F;code&gt; trait, which gives control
over the &lt;code&gt;Read&lt;&#x2F;code&gt; cursor in types that support it.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;regular&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;No, files in &lt;code&gt;&#x2F;proc&lt;&#x2F;code&gt; are not &quot;regular files&quot;. Yes, I know sockets are technically file descriptors.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;In Rust the &lt;code&gt;Iterator&lt;&#x2F;code&gt; trait provides no mechanism to control the underlying
cursor, despite its similarities to &lt;code&gt;Read&lt;&#x2F;code&gt;. A language that does provide an
abstraction for this is C++ in the form of
&lt;a href=&quot;https:&#x2F;&#x2F;en.cppreference.com&#x2F;w&#x2F;cpp&#x2F;iterator&#x2F;random_access_iterator&quot;&gt;&lt;code&gt;random_access_iterator&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
This is a C++ concept (trait-alike) that further refines
&lt;code&gt;bidirectional_iterator&lt;&#x2F;code&gt;. My C++ knowledge is limited, so I&#x27;d rather quote the
docs directly than attempt to paraphrase:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;[...] random_access_iterator refines bidirectional_iterator by adding support for constant time advancement with the &lt;code&gt;+=&lt;&#x2F;code&gt;, &lt;code&gt;+&lt;&#x2F;code&gt;, &lt;code&gt;-=&lt;&#x2F;code&gt;, and &lt;code&gt;-&lt;&#x2F;code&gt; operators, constant time computation of distance with &lt;code&gt;-&lt;&#x2F;code&gt;, and array notation with subscripting &lt;code&gt;[]&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Being able to directly control the cursor in &lt;code&gt;Iterator&lt;&#x2F;code&gt; implementations could
prove useful when working with in-memory collection types like &lt;code&gt;Vec&lt;&#x2F;code&gt;, as well as
when working with remote objects such as paginated API endpoints. The obvious
starting point for such a trait would be to mirror the existing &lt;code&gt;io::Seek&lt;&#x2F;code&gt; trait
and adapt it to be a subtrait of &lt;code&gt;Iterator&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Enumeration of possible methods to seek within an iterator.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub enum &lt;&#x2F;span&gt;&lt;span&gt;SeekFrom {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Sets the offset to the specified index.
&lt;&#x2F;span&gt;&lt;span&gt;    Start(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Sets the offset to the size of this object plus the specified index.
&lt;&#x2F;span&gt;&lt;span&gt;    End(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;isize&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Sets the offset to the current position plus the specified index.
&lt;&#x2F;span&gt;&lt;span&gt;    Current(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;isize&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; An iterator with a cursor which can be moved.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;SeekingIterator: Iterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Seek to an offset in an iterator.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;seek&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;pos&lt;&#x2F;span&gt;&lt;span&gt;: SeekFrom) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;compile-time-iterator&quot;&gt;Compile-Time Iterator&lt;&#x2F;h2&gt;
&lt;p&gt;In Rust we can use &lt;code&gt;const {}&lt;&#x2F;code&gt; blocks to execute code during compilation. Only
&lt;code&gt;const fn&lt;&#x2F;code&gt; functions can be called from &lt;code&gt;const {}&lt;&#x2F;code&gt; blocks. &lt;code&gt;const fn&lt;&#x2F;code&gt; free
functions and methods are stable, but &lt;code&gt;const fn&lt;&#x2F;code&gt; trait methods are not. This
means that traits like &lt;code&gt;Iterator&lt;&#x2F;code&gt; are not yet callable from &lt;code&gt;const {}&lt;&#x2F;code&gt; blocks,
and so neither are &lt;code&gt;for..in&lt;&#x2F;code&gt; expressions.&lt;&#x2F;p&gt;
&lt;p&gt;We know we want to support iteration in &lt;code&gt;const {}&lt;&#x2F;code&gt; blocks, but we don&#x27;t yet know
how we want to spell both the trait declaration and trait bounds. The most
interesting open question here is how we will end up passing the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;marker&#x2F;trait.Destruct.html&quot;&gt;&lt;code&gt;Destruct&lt;&#x2F;code&gt;
trait&lt;&#x2F;a&gt; around, which
is necessary to enable types to be droppable in &lt;code&gt;const&lt;&#x2F;code&gt; contexts. This leads to
additional questions around whether const trait bounds should imply const
&lt;code&gt;Destruct&lt;&#x2F;code&gt;. And whether the &lt;code&gt;const&lt;&#x2F;code&gt; annotation should be part of the trait
declaration, the individual methods, or perhaps both.&lt;&#x2F;p&gt;
&lt;p&gt;This post is not the right venue to discuss all tradeoffs. But to give a sense
of what a compile-time-compatible &lt;code&gt;Iterator&lt;&#x2F;code&gt; trait might look like: here is a
variant where both the trait and individual methods are annotated with &lt;code&gt;const&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub const trait &lt;&#x2F;span&gt;&lt;span&gt;IntoIterator {                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `const`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;IntoIter: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span&gt;Iterator&amp;lt;Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `const`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;IntoIter;       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `const`
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub const trait &lt;&#x2F;span&gt;&lt;span&gt;Iterator {                                     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `const`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `const`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;size_hint&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;, Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) { .. } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `const`
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;lending-iterator&quot;&gt;Lending Iterator&lt;&#x2F;h2&gt;
&lt;p&gt;While there are plenty of iterators in the stdlib today that yield references to
items, the values that are being referenced are never owned by the iterator
itself. In order to write iterators which owns the items it yields and yields
them by-reference, the associated item type in iterator needs a lifetime:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;IntoIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;                                               &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Lifetime
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;;                                               &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Bound
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;IntoIter: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; Iterator&amp;lt;Item&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Lifetime
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;IntoIter;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Iterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;                                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Lifetime
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;;                                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Bound
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;lt;&amp;#39;_&amp;gt;&amp;gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Lifetime
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;size_hint&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;, Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) { .. }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There has been talk about adding a &lt;code&gt;&#x27;self&lt;&#x2F;code&gt; lifetime to the language as a
shorthand for &lt;code&gt;where Self:&#x27;a&lt;&#x2F;code&gt;. But even with that addition this set of
signatures is not for the faint of heart. The reason for that is that it makes
use of GATs, which are both useful and powerful — but are for all intents and
purposes an expert-level type-system feature, and can be a little tricky to
reason about.&lt;&#x2F;p&gt;
&lt;p&gt;Lending iteration is also going to be important when we add dedicated syntax to
construct iterators using the &lt;code&gt;yield&lt;&#x2F;code&gt; keyword. The following example shows a
&lt;code&gt;gen {}&lt;&#x2F;code&gt; block which creates a string and then yields a reference to it. This
perfectly&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#heap&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; matches onto the &lt;code&gt;Iterator&lt;&#x2F;code&gt; trait we’ve defined:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;heap&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;Remember that strings are heap-allocated so we don’t need to account for address-sensitivity. While the compiler can&#x27;t yet perform this desugaring, there is nothing in the language prohibiting it.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; iter = gen {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; name = String::from(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Chashu&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;yield&lt;&#x2F;span&gt;&lt;span&gt; &amp;amp;name; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Borrows a local value stored on the heap.
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;iterator-with-a-return-value&quot;&gt;Iterator with a Return Value&lt;&#x2F;h2&gt;
&lt;p&gt;The current &lt;code&gt;Iterator&lt;&#x2F;code&gt; trait has an associated type &lt;code&gt;Item&lt;&#x2F;code&gt;, which maps to the
&lt;code&gt;yield&lt;&#x2F;code&gt; keyword in Rust. But it has no associated type that maps to the &lt;code&gt;return&lt;&#x2F;code&gt;
keyword. A way to think about iterators today is that their return type is
hard-coded to unit. If we want to enable generator functions and blocks to be
written which can not just &lt;code&gt;yield&lt;&#x2F;code&gt;, but also &lt;code&gt;return&lt;&#x2F;code&gt;, we&#x27;ll need some way to
express that.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; counting_iter = gen {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; total = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; item in iter {
&lt;&#x2F;span&gt;&lt;span&gt;        total += &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;yield&lt;&#x2F;span&gt;&lt;span&gt; item;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Yields one type.
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    total                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Returns another type.
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The obvious way to write a trait for &quot;an iterator which can return&quot; is to give
&lt;code&gt;Iterator&lt;&#x2F;code&gt; an additional associated item &lt;code&gt;Output&lt;&#x2F;code&gt; which maps to the logical
return value. In order to be able to express fuse semantics, the function &lt;code&gt;next&lt;&#x2F;code&gt;
needs to be able to return three different states:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Yielding the associated type &lt;code&gt;Item&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Returning the associated type &lt;code&gt;Output&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;The iterator has been exhausted (done)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;One way to do this would be for &lt;code&gt;next&lt;&#x2F;code&gt; to return &lt;code&gt;Option&amp;lt;ControlFlow&amp;gt;&lt;&#x2F;code&gt;, where
&lt;code&gt;Some(Continue)&lt;&#x2F;code&gt; maps to &lt;code&gt;yield&lt;&#x2F;code&gt;, &lt;code&gt;Some(Break)&lt;&#x2F;code&gt; maps to &lt;code&gt;return&lt;&#x2F;code&gt;, and &lt;code&gt;None&lt;&#x2F;code&gt;
maps to done. Without a final &quot;done&quot; state, calling &lt;code&gt;next&lt;&#x2F;code&gt; again on an iterator
after it&#x27;s finished yielding values would likely always have to panic. This is
what most futures do in async Rust, and is going to be a problem if we ever want
to guarantee panic-freedom.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;IntoIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;                                            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Output
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;IntoIter:
&lt;&#x2F;span&gt;&lt;span&gt;        Iterator&amp;lt;Output = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output, Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Output
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;IntoIter;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Iterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;                                           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Output
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;        -&amp;gt; Option&amp;lt;ControlFlow&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;&amp;gt;;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Output
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;size_hint&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;, Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) { .. }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The way this would work on the caller side and in combinators is quite
interesting. Starting with the provided
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.Iterator.html#method.for_each&quot;&gt;&lt;code&gt;for_each&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
method: it will want to return &lt;code&gt;Iterator::Output&lt;&#x2F;code&gt; rather than &lt;code&gt;()&lt;&#x2F;code&gt; once the
iterator has completed. Crucially the closure &lt;code&gt;F&lt;&#x2F;code&gt; provided to &lt;code&gt;for_each&lt;&#x2F;code&gt; only
operates on &lt;code&gt;Self::Output&lt;&#x2F;code&gt;, and has no knowledge of &lt;code&gt;Self::Output&lt;&#x2F;code&gt;. Because if
the closure did have direct knowledge of &lt;code&gt;Output&lt;&#x2F;code&gt;, it could short-circuit by
returning &lt;code&gt;Output&lt;&#x2F;code&gt; sooner than expected which is a different kind of iterator
than having a return value.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;for_each&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;F&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;: F) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Output
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;: Sized,
&lt;&#x2F;span&gt;&lt;span&gt;    F: FnMut(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item),
&lt;&#x2F;span&gt;&lt;span&gt;{ .. }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we were to transpose &quot;iterator with return value&quot; to &lt;code&gt;for..in&lt;&#x2F;code&gt; things get
even more interesting still. In Rust &lt;code&gt;loop&lt;&#x2F;code&gt; expressions can themselves evaluate
to non-unit types by calling &lt;code&gt;break&lt;&#x2F;code&gt; with some value. &lt;code&gt;for..in&lt;&#x2F;code&gt; expressions
cannot do this in the general case yet, except for the handling of errors using
&lt;code&gt;?&lt;&#x2F;code&gt;. But it&#x27;s not hard to see how this could be made to work, conceptually this
is equivalent to calling &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.Iterator.html#method.try_for_each&quot;&gt;&lt;code&gt;Iterator::try_for_each&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and returning
&lt;code&gt;Some(Break(value))&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; ty: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; item in iter {  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Evaluates to a `u32`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32                   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Calls `break` from the loop body
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Assuming we have an &lt;code&gt;Iterator&lt;&#x2F;code&gt; with its own return value, that would mean
&lt;code&gt;for..in&lt;&#x2F;code&gt; expressions would be able to evaluate to non-unit return types without
calling &lt;code&gt;break&lt;&#x2F;code&gt; from within the loop&#x27;s body:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; ty: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; item in iter {  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Evaluates to a `u32`
&lt;&#x2F;span&gt;&lt;span&gt;    dbg!(item);                   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Doesn&amp;#39;t `break` from the loop body
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This of course leads to questions about how to combine an &quot;iterator with a
return value&quot; and &quot;using &lt;code&gt;break&lt;&#x2F;code&gt; from inside a &lt;code&gt;for..in&lt;&#x2F;code&gt; expression&quot;. I&#x27;ll leave
that as an exercise to the reader on how to spell out (I&#x27;m certain it can be
done, I just think it&#x27;s a fun one). Generalizing all modes of early returns from
&lt;code&gt;for..in&lt;&#x2F;code&gt; expressions to invocations of &lt;code&gt;for_each&lt;&#x2F;code&gt; combinators is an interesting
challenge that we&#x27;ll cover in more detail later on when we discuss
short-circuiting (fallible) iterators.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;iterator-with-a-next-argument&quot;&gt;Iterator with a Next Argument&lt;&#x2F;h2&gt;
&lt;p&gt;In generator blocks the &lt;code&gt;yield&lt;&#x2F;code&gt; keyword can be used to repeatedly yield values
from an iterator. But what if the caller doesn&#x27;t just want to obtain values, but
also pass new values back into the iterator? That would require for &lt;code&gt;yield&lt;&#x2F;code&gt; to be able
evaluate to a non-unit type. Iterators that have this functionality are often
referred to as &quot;coroutines&quot;, and they are being particularly useful when implementing &lt;a href=&quot;https:&#x2F;&#x2F;sans-io.readthedocs.io&#x2F;how-to-sans-io.html&quot;&gt;I&#x2F;O-Free Protocols&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Some RPC protocol
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;Proto {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Some protocol state
&lt;&#x2F;span&gt;&lt;span&gt;    MsgLen(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; rpc_handler = gen {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; len = message.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; next_state = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;yield&lt;&#x2F;span&gt;&lt;span&gt; Proto::MsgLen(len); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `yield` evaluates to a value
&lt;&#x2F;span&gt;&lt;span&gt;    ..
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In order to support this, &lt;code&gt;Iterator::next&lt;&#x2F;code&gt; needs to be able to take an
additional argument in the form of a new associated type &lt;code&gt;Args&lt;&#x2F;code&gt;. This associated
type has the same name as the input arguments to &lt;code&gt;Fn&lt;&#x2F;code&gt; and &lt;code&gt;AsyncFn&lt;&#x2F;code&gt;. If
&quot;iterator with a next argument&quot; can be thought of as representing a &quot;coroutine&quot;,
the &lt;code&gt;Fn&lt;&#x2F;code&gt; family of traits can be thought of as representing a regular &quot;routine&quot;
(function).&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;IntoIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Args;                                          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Args
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;IntoIter:
&lt;&#x2F;span&gt;&lt;span&gt;        Iterator&amp;lt;Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item, Args = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Args&amp;gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Args
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;IntoIter;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Iterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Args;                                                  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Args
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;args&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Args) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Args
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;size_hint&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;, Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) { .. }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here too it&#x27;s interesting to consider the caller side. Starting with a
hypothetical &lt;code&gt;for_each&lt;&#x2F;code&gt; function: it would need to be able to take an initial
value passed to &lt;code&gt;next&lt;&#x2F;code&gt;, and then from the closure be able to return additional
values passed to subsequent invocations of &lt;code&gt;next&lt;&#x2F;code&gt;. The signature for that would
look like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;for_each&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;F&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;args&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;: F) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Args
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;: Sized,
&lt;&#x2F;span&gt;&lt;span&gt;    F: FnMut(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Args,      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Args
&lt;&#x2F;span&gt;&lt;span&gt;{ .. }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To better illustrate how this would work and build up some intuition, consider
manual calls to &lt;code&gt;next&lt;&#x2F;code&gt; inside of a loop. We would start by constructing some
initial state that is passed to the first invocation of &lt;code&gt;next&lt;&#x2F;code&gt;. This will
produce an item that can be used to construct the next argument to &lt;code&gt;next&lt;&#x2F;code&gt;. And so on, until the iterator has no more items left to yield:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; iter = some_value.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; arg = some_initial_value;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; loop as long as there are items to yield
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(item) = iter.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(arg) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; use `item` and compute the next `arg`
&lt;&#x2F;span&gt;&lt;span&gt;    arg = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;process_item&lt;&#x2F;span&gt;&lt;span&gt;(item);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we were to iterate over an iterator with a next function using a &lt;code&gt;for..in&lt;&#x2F;code&gt;
expression, the equivalent of returning a value from a closure would be either
to &lt;code&gt;continue&lt;&#x2F;code&gt; with a value. This could potentially also be the final expression
in the loop body, which you can think of itself being an implied &lt;code&gt;continue&lt;&#x2F;code&gt;
today. The only question remaining is how to pass initial values on loop
construction, but that mainly seems like an exercise in syntax design:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Passing a value to the `next` function seems like
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; it would logically map to `continue`-expressions.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; (passing initial state to the loop intentionally omitted)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; item in iter {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;continue &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;process_item&lt;&#x2F;span&gt;&lt;span&gt;(item);   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `continue` with value
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; You can think of `for..in` expressions as having
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; an implied `continue ()` at the end. Like functions
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; have an implied `return ()`. What if that could take
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; a value?
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; (passing initial state to the loop intentionally omitted)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; item in iter {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;process_item&lt;&#x2F;span&gt;&lt;span&gt;(item)             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `continue` with value
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&quot;iterator with return value&quot; and &quot;iterator with next argument&quot; feel like they
map particularly well to &lt;code&gt;break&lt;&#x2F;code&gt; and &lt;code&gt;continue&lt;&#x2F;code&gt;. I think of them as duals,
enabling both expressions to carry non-unit types. This feels like it might be
an important insight that I haven&#x27;t seen anyone bring up before.&lt;&#x2F;p&gt;
&lt;p&gt;Being able to pass a value to &lt;code&gt;next&lt;&#x2F;code&gt; is one of the hallmark features of the
&lt;code&gt;Coroutine&lt;&#x2F;code&gt; trait in the stdlib. However unlike the trait sketch we provided
here, in &lt;code&gt;Coroutine&lt;&#x2F;code&gt; the type of the value passed to &lt;code&gt;next&lt;&#x2F;code&gt; is defined as a
generic param on the trait rather than an associated type. Presumably that is so
that &lt;code&gt;Coroutine&lt;&#x2F;code&gt; can have multiple implementations on the same type that depend
on the input type. I searched whether this was actually being used today, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;search?q=repo%3Arust-lang%2Frust+%22impl+Coroutine%22&amp;amp;type=code&amp;amp;repo=&amp;amp;langOverride=&amp;amp;start_value=1&amp;amp;p=3&quot;&gt;and
it doesn&#x27;t seem to
be&lt;&#x2F;a&gt;.
Which is why I suspect it is likely fine to use an associated type for the input
arguments.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;short-circuiting-iterator&quot;&gt;Short-Circuiting Iterator&lt;&#x2F;h2&gt;
&lt;p&gt;While it is possible to return &lt;code&gt;Try&lt;&#x2F;code&gt;-types such as &lt;code&gt;Result&lt;&#x2F;code&gt; and &lt;code&gt;Option&lt;&#x2F;code&gt; from an
iterator today, it isn&#x27;t yet possible is to immediately stop execution in the
case of an error [^not-panic]. This behavior is typically referred to as
&quot;short-circuiting&quot;: halting normal operation and triggering an
exceptional state (like an electrical breaker would in a building).&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;not_panic&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;By that I mean: an error, not a panic.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;In unstable Rust we have &lt;code&gt;try {}&lt;&#x2F;code&gt; blocks that rely on the unstable &lt;code&gt;Try&lt;&#x2F;code&gt; trait,
but we don&#x27;t yet have &lt;code&gt;try fn&lt;&#x2F;code&gt; functions. If we want these to function in traits
the way we&#x27;d want them to, they will have to desugar to &lt;code&gt;impl Try&lt;&#x2F;code&gt;. Rather than
speculate about what a potential &lt;code&gt;try fn&lt;&#x2F;code&gt; syntax might look like in the future,
we&#x27;ll be writing our samples using &lt;code&gt;-&amp;gt; impl Try&lt;&#x2F;code&gt; directly. Here is what the
&lt;code&gt;Try&lt;&#x2F;code&gt; (and &lt;code&gt;FromResidual&lt;&#x2F;code&gt;) traits look like today:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The `?` operator and `try {}` blocks.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Try: FromResidual {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The type of the value produced by `?`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; when _not_ short-circuiting.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The type of the value passed to `FromResidual::from_residual`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; as part of ? when short-circuiting.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Residual;
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Constructs the type from its `Output` type.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;from_output&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;output&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Used in ? to decide whether the operator should produce
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; a value ( or propagate a value back to the caller.    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;branch&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; ControlFlow&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Residual, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Used to specify which residuals can be converted
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; into which `Try` types.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;FromResidual&amp;lt;R = &amp;lt;Self as Try&amp;gt;::Residual&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Constructs the type from a compatible `Residual` type.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;from_residual&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;residual&lt;&#x2F;span&gt;&lt;span&gt;: R) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can think of a short-circuiting iterator as a special case of an &quot;iterator
with return value&quot;. In its base form, it will only return early in case of an
exception while its logical return type remains hard-coded to unit. The return
type of &lt;code&gt;fn next&lt;&#x2F;code&gt; should be an &lt;code&gt;impl Try&lt;&#x2F;code&gt; returning an &lt;code&gt;Option&lt;&#x2F;code&gt;, with the value
of &lt;code&gt;Residual&lt;&#x2F;code&gt; set to the associated &lt;code&gt;Residual&lt;&#x2F;code&gt; type. This allows all combinators
to share the same &lt;code&gt;Residual&lt;&#x2F;code&gt;, enabling types to flow.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;IntoIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Residual;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;IntoIter: Iterator&amp;lt;
&lt;&#x2F;span&gt;&lt;span&gt;        Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item,
&lt;&#x2F;span&gt;&lt;span&gt;        Residual = Residual   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Residual
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;IntoIter;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Iterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Residual;                   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Residual
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; impl Try&amp;lt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← impl Try
&lt;&#x2F;span&gt;&lt;span&gt;        Output = Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        Residual = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Residual,   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Residual
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we once again consider the caller, we&#x27;ll want to provide a way for &lt;code&gt;for..in&lt;&#x2F;code&gt;
expressions to short-circuit. What&#x27;s interesting here is that the base iterator
trait already provides a
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.Iterator.html#method.try_for_each&quot;&gt;&lt;code&gt;try_for_each&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;,
method. The difference between that method and the &lt;code&gt;for_each&lt;&#x2F;code&gt; we&#x27;re about to see
is how the type of &lt;code&gt;Residual&lt;&#x2F;code&gt; is obtained. In &lt;code&gt;try_for_each&lt;&#x2F;code&gt; the value is local
to the method, while if the trait itself is &quot;short-circuiting&quot; the type of
&lt;code&gt;Residual&lt;&#x2F;code&gt; is determined by the associated &lt;code&gt;Self::Residual&lt;&#x2F;code&gt; type. Or put
differently: in a short-circuiting iterator the type we short-circuit with is a
property of the trait rather than a property of the method.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;for_each&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;F, R&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;: F) -&amp;gt; R                  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Return type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;: Sized,
&lt;&#x2F;span&gt;&lt;span&gt;    F: FnMut(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item) -&amp;gt; R,                      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Return type
&lt;&#x2F;span&gt;&lt;span&gt;    R: Try&amp;lt;Output = (), Residual = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Residual&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `impl Try`
&lt;&#x2F;span&gt;&lt;span&gt;{ .. }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As mentioned earlier on in this post: the interaction between &quot;iterator with a
return type&quot; and &quot;short-circuiting iterator&quot; is an interesting one. Returning
&lt;code&gt;Option&amp;lt;ControlFlow&amp;gt;&lt;&#x2F;code&gt; from &lt;code&gt;fn next&lt;&#x2F;code&gt; is able to encode three distinct states,
but this combination of capabilities requires us to encode four states:&lt;&#x2F;p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;yield a next item&lt;&#x2F;li&gt;
&lt;li&gt;break with a residual&lt;&#x2F;li&gt;
&lt;li&gt;return a final output&lt;&#x2F;li&gt;
&lt;li&gt;iterator done (idempotent)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The reason why we want to be able to encode a signature like this is because
when writing &lt;code&gt;gen fn&lt;&#x2F;code&gt; functions it is entirely reasonable to want to have a
return type, short-circuit on error using &lt;code&gt;?&lt;&#x2F;code&gt;, and also &lt;code&gt;yield&lt;&#x2F;code&gt; values. This
works like regular functions today, but with the added capability to invoke
&lt;code&gt;yield&lt;&#x2F;code&gt;. The naive way of encoding this would be to return an &lt;code&gt;impl Try&lt;&#x2F;code&gt; of
&lt;code&gt;Option&amp;lt;ControlFlow&amp;lt;_&amp;gt;&amp;gt;&lt;&#x2F;code&gt; with distinct associated types for &lt;code&gt;Item&lt;&#x2F;code&gt;, &lt;code&gt;Output&lt;&#x2F;code&gt;,
and &lt;code&gt;Residual&lt;&#x2F;code&gt;. This does however feel like it is starting to get a little out
of hand, though perhaps a first-class &lt;code&gt;try fn&lt;&#x2F;code&gt; notation might provide some
relief.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;IntoIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;                           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `Output` 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Residual;                         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `Residual` 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;IntoIterator: Iter&amp;lt;
&lt;&#x2F;span&gt;&lt;span&gt;        Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item,
&lt;&#x2F;span&gt;&lt;span&gt;        Residual = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Residual,         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `Residual` 
&lt;&#x2F;span&gt;&lt;span&gt;        Output = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output,             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `Output` 
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;IntoIter;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Iterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;                     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `Output`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Residual;                   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `Residual`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; impl Try&amp;lt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `impl Try` 
&lt;&#x2F;span&gt;&lt;span&gt;        Output = Option&amp;lt;ControlFlow&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `ControlFlow
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output,            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `Output
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item,
&lt;&#x2F;span&gt;&lt;span&gt;        &amp;gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        Residual = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Residual,   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `Residual` 
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;address-sensitive-iterator&quot;&gt;Address-Sensitive Iterator&lt;&#x2F;h2&gt;
&lt;p&gt;Rust&#x27;s generator transformation may create self-referential types. That is:
types which have fields that borrow from other fields on the same type. We call
these types &quot;address-sensitive&quot; because once the type has been constructed, its
address in memory must remain stable. This comes up when writing &lt;code&gt;gen {}&lt;&#x2F;code&gt; blocks
that have stack-allocated locals &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#head-locals&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; that are kept live across
&lt;code&gt;yield&lt;&#x2F;code&gt;-expressions. What is or isn&#x27;t a &quot;stack-allocated local&quot; can get a little
complicated. But it&#x27;s important to highlight that for example calling
&lt;code&gt;IntoIterator::into_iter&lt;&#x2F;code&gt; on a type and re-yielding all items is something that
just works
(&lt;a href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=nightly&amp;amp;mode=debug&amp;amp;edition=2024&amp;amp;gist=e004e82ac881d53793e2bd37523b813e&quot;&gt;playground&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;head-locals&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;This affects heap-allocated locals too, but that&#x27;s not a limitation of the language, only one of the impl.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; This example works today
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; iter = gen {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cat_iter = cats.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; cat in cat_iter {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;yield&lt;&#x2F;span&gt;&lt;span&gt; cat;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And to give a sense of what for example does not work, here is one of the
samples Tmandry (T-Lang) collected. This creates an intermediate borrow, which
results in the error: &quot;Borrow may still be in use when &lt;code&gt;gen&lt;&#x2F;code&gt; fn body yields&quot;
(&lt;a href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=nightly&amp;amp;mode=debug&amp;amp;edition=2024&amp;amp;gist=e004e82ac881d53793e2bd37523b813e&quot;&gt;playground&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;gen &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;iter_set_rc&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T: Clone&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;xs&lt;&#x2F;span&gt;&lt;span&gt;: Rc&amp;lt;RefCell&amp;lt;HashSet&amp;lt;T&amp;gt;&amp;gt;&amp;gt;) ... {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; x in xs.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;borrow&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;yield&lt;&#x2F;span&gt;&lt;span&gt; x.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In order to enable examples like the last one to work, Rust needs to be able to
express some form of &quot;address-sensitive iterator&quot;. The obvious starting point
would be to mint a new trait &lt;code&gt;PinnedIterator&lt;&#x2F;code&gt; which changes the self-type of
&lt;code&gt;next&lt;&#x2F;code&gt; to take a &lt;code&gt;Pin&amp;lt;&amp;amp;mut Self&amp;gt;&lt;&#x2F;code&gt; rather than &lt;code&gt;&amp;amp;mut self&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;IntoIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;IntoIter: Iterator&amp;lt;Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;IntoIter;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Iterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `Pin&amp;lt;&amp;amp;mut Self&amp;gt;`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;size_hint&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;, Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) { .. }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Enumerating all the problems of &lt;code&gt;Pin&lt;&#x2F;code&gt; is worth its own blog post. But still, it
seems important enough to point out that this definition has what Rust for Linux
calls &lt;a href=&quot;https:&#x2F;&#x2F;rust-for-linux.com&#x2F;the-safe-pinned-initialization-problem&quot;&gt;The Safe Pinned Initialization
Problem&lt;&#x2F;a&gt;.
&lt;code&gt;IntoIterator::into_iter&lt;&#x2F;code&gt; cannot return a type that is address-sensitive at time
of construction, instead address-sensitivity is something that can only be
guaranteed at a later point once the type is &lt;code&gt;pin!&lt;&#x2F;code&gt;ned in place.&lt;&#x2F;p&gt;
&lt;p&gt;At the start of this post I used the phrase: &quot;(soft-)deprecation of the
&lt;code&gt;Iterator&lt;&#x2F;code&gt; trait&quot;. With that I was referring to one proposed idea to enable &lt;code&gt;gen {}&lt;&#x2F;code&gt; to return a new trait &lt;code&gt;Generator&lt;&#x2F;code&gt; with the same signature as our example.
As well as some bridging impls for the purposes of compatibility. The core of
the compat system would be as follows:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; All `Iterator`s are `Generator`s
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;I: IntoIterator&amp;gt; IntoGenerator &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;I {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item = I::Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;IntoGen = IteratorGenerator&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;I::&lt;&#x2F;span&gt;&lt;span&gt;IntoIter&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into_gen&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;IntoGen {
&lt;&#x2F;span&gt;&lt;span&gt;        IteratorGenerator(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;())
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Only pinned `Generator`s are `Iterator`s
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;G&amp;gt; Iterator &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Pin&amp;lt;G&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    G: DerefMut,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;G::&lt;&#x2F;span&gt;&lt;span&gt;Target: Generator,
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item = &amp;lt;&amp;lt;G as Deref&amp;gt;::Target as Generator&amp;gt;::Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        Generator::next(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut&lt;&#x2F;span&gt;&lt;span&gt;())
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This creates a situation that I&#x27;ve been describing as &quot;one-and-a-half-way
compat&quot;, as opposed to the usual two-way-compat. And we need two-way-compat to
not be a breaking change. This leads to a situation where changing a bound from
taking &lt;code&gt;Iterator&lt;&#x2F;code&gt; to &lt;code&gt;Generator&lt;&#x2F;code&gt; is backwards-compatible. But changing an impl
from returning an &lt;code&gt;Iterator&lt;&#x2F;code&gt; to returning a &lt;code&gt;Generator&lt;&#x2F;code&gt; is not
backwards-compatible. The obvious solution then would be to migrate the entire
ecosystem to take &lt;code&gt;Generator&lt;&#x2F;code&gt; bounds everywhere. Coupled with &lt;code&gt;gen {}&lt;&#x2F;code&gt; only ever
returning &lt;code&gt;Generator&lt;&#x2F;code&gt; and not &lt;code&gt;Iterator&lt;&#x2F;code&gt;: that is a deprecation of &lt;code&gt;Iterator&lt;&#x2F;code&gt; in
all but name.&lt;&#x2F;p&gt;
&lt;p&gt;At first sight it might seem like we&#x27;re being forced into deprecating &lt;code&gt;Iterator&lt;&#x2F;code&gt;
because of the limitations of &lt;code&gt;Pin&lt;&#x2F;code&gt;. The obvious answer to that would be to
solve the issues with &lt;code&gt;Pin&lt;&#x2F;code&gt; by replacing it with something
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;self-referential-types&#x2F;&quot;&gt;better&lt;&#x2F;a&gt;. But that creates
a false dichotomy: there is nothing forcing us to make a decision on this today.
As we established at the start of this section: a surprising amount of use cases
already work without the need for address-sensitive iterators. And as we&#x27;ve seen
throughout this post: address-sensitive iteration is far from the only feature
that &lt;code&gt;gen {}&lt;&#x2F;code&gt; blocks will not be able to support on day one.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;iterator-guaranteeing-destruct&quot;&gt;Iterator Guaranteeing Destruct&lt;&#x2F;h2&gt;
&lt;p&gt;The current formulation of &lt;code&gt;thread::scope&lt;&#x2F;code&gt; requires that the thread it’s called
on remains blocked until all threads have been joined. This requires stepping
into a closure and executing all code within that. Contrast this with something
like &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-concurrency&#x2F;latest&#x2F;futures_concurrency&#x2F;future&#x2F;struct.FutureGroup.html&quot;&gt;&lt;code&gt;FutureGroup&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
which logically owns computations and can be freely moved around. The values of
the futures resolved within can in turn be yielded out. But unlike
&lt;code&gt;thread::scope&lt;&#x2F;code&gt; it can’t guarantee that all computations will complete, and so
a parallel version of &lt;code&gt;FutureGroup&lt;&#x2F;code&gt; can&#x27;t mutably hold onto mutable borrows the
way &lt;code&gt;thread::scope&lt;&#x2F;code&gt; can.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; A usage example of `thread::scope`,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; the ability to spawn new threads
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; is only available inside the closure.
&lt;&#x2F;span&gt;&lt;span&gt;thread::scope(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;| {
&lt;&#x2F;span&gt;&lt;span&gt;    s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(|| ..);
&lt;&#x2F;span&gt;&lt;span&gt;    s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(|| ..);
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← All threads are joined here.
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; A usage example of `FutureGroup`,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; no closures required.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; group = FutureGroup::new();
&lt;&#x2F;span&gt;&lt;span&gt;group.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;group.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;group.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;for_each&lt;&#x2F;span&gt;&lt;span&gt;(|_| ()).await;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we want to write a type similar to &lt;code&gt;FutureGroup&lt;&#x2F;code&gt; with the same guarantees as
&lt;code&gt;thread::scope&lt;&#x2F;code&gt;, we&#x27;d either need to guarantee that &lt;code&gt;FutureGroup&lt;&#x2F;code&gt; can never be
dropped or guarantee that &lt;code&gt;FutureGroup&lt;&#x2F;code&gt;&#x27;s &lt;code&gt;Drop&lt;&#x2F;code&gt; impl is always run. It turns
out that it&#x27;s rather impractical to have types that can&#x27;t be dropped in a
language where every function may panic. So the only real option here are to
have types whose destructors are guaranteed to run.&lt;&#x2F;p&gt;
&lt;p&gt;The most plausible way we know of to do this would be by introducing a new auto
trait &lt;code&gt;Leak&lt;&#x2F;code&gt;, disallowing types from being passed to &lt;code&gt;mem::forget&lt;&#x2F;code&gt;, &lt;code&gt;Box::leak&lt;&#x2F;code&gt;,
and so on. For more on the design, read &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;linear-types-one-pager&#x2F;&quot;&gt;Linear Types
One-Pager&lt;&#x2F;a&gt;. Because &lt;code&gt;Leak&lt;&#x2F;code&gt;
is an auto-trait, we could compose it with the existing &lt;code&gt;Iterator&lt;&#x2F;code&gt; and
&lt;code&gt;IntoIterator&lt;&#x2F;code&gt; traits, similar to &lt;code&gt;Send&lt;&#x2F;code&gt; and &lt;code&gt;Move&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;linear_sink&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;: impl IntoIterator&amp;lt;IntoIter: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;Leak&amp;gt;) { .. }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;async-iterator&quot;&gt;Async Iterator&lt;&#x2F;h2&gt;
&lt;p&gt;In Rust the &lt;code&gt;async&lt;&#x2F;code&gt; keyword can transform imperative function bodies into state
machines that can be manually advanced by calling the &lt;code&gt;Future::poll&lt;&#x2F;code&gt; method.
Under the hood this is done using what is called a &lt;em&gt;coroutine transform&lt;&#x2F;em&gt;, which
is the same transform we use to desugar &lt;code&gt;gen {}&lt;&#x2F;code&gt; blocks with. But that&#x27;s
just the mechanics of it; the &lt;code&gt;async&lt;&#x2F;code&gt; keyword in Rust also introduces &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;why-async-rust&#x2F;&quot;&gt;two new
capabilities&lt;&#x2F;a&gt;: ad-hoc concurrency
and ad-hoc cancellation. Together these capabilities can be combined to create
new control-flow operations, like
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-concurrency&#x2F;latest&#x2F;futures_concurrency&#x2F;future&#x2F;trait.FutureExt.html#tymethod.race&quot;&gt;&lt;code&gt;Future::race&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;code&gt;Future::timeout&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Async Functions in Traits were stabilized one year ago in Rust 1.75, enabling
the use of  &lt;code&gt;async fn&lt;&#x2F;code&gt; in traits. Making the &lt;code&gt;Iterator&lt;&#x2F;code&gt;trait work with &lt;code&gt;async&lt;&#x2F;code&gt;
is mostly a matter of adding an &lt;code&gt;async&lt;&#x2F;code&gt; prefix to &lt;code&gt;next&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;IntoIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;IntoIter: Iterator&amp;lt;Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;IntoIter;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Iterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← async
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;size_hint&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;, Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) { .. }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While the &lt;code&gt;next&lt;&#x2F;code&gt; method here would be annotated with the &lt;code&gt;async&lt;&#x2F;code&gt; keyword, the
&lt;code&gt;size_hint&lt;&#x2F;code&gt; method should probably not be. The reason for that is that it acts
as a simple getter, and it really shouldn&#x27;t be performing any asynchronous
computation. It&#x27;s also unclear whether &lt;code&gt;into_iter&lt;&#x2F;code&gt; should be an &lt;code&gt;async fn&lt;&#x2F;code&gt; or
not. There is probably a pattern to be established here, and it might very well
be.&lt;&#x2F;p&gt;
&lt;p&gt;An combination of iterator variants that&#x27;s been of some interest recently is an
address-sensitive async iterator. We could imagine writing an address-sensitive
async iterator by making &lt;code&gt;next&lt;&#x2F;code&gt; take &lt;code&gt;self: Pin&amp;lt;&amp;amp;mut Self&amp;gt;&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;IntoIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;IntoIter: Iterator&amp;lt;Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;IntoIter;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Iterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← async + `Pin&amp;lt;&amp;amp;mut Self&amp;gt;`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;size_hint&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;, Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) { .. }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This signature is likely to confuse some people. &lt;code&gt;async fn next&lt;&#x2F;code&gt; return an &lt;code&gt;impl Future&lt;&#x2F;code&gt; which itself must be pinned prior to being polled. In this example we are
separately requiring that &lt;code&gt;Self&lt;&#x2F;code&gt; is also pinned. That is because &quot;the state of
the iterator&quot; and &quot;the state of the future&quot; are not the same state. We
intuitively understand this when working with non-async address-sensitive
iterators: the locals created within the &lt;code&gt;next&lt;&#x2F;code&gt; are not captured by the
enclosing iterator, and are free to be stack-pinned for the duration of the call
to &lt;code&gt;next&lt;&#x2F;code&gt;. But when working with an asynchronous address-sensitive iterator,
for some reason people seem to assume that all locals defined in &lt;code&gt;fn next&lt;&#x2F;code&gt; now
need to be owned by the iterator and not the future.&lt;&#x2F;p&gt;
&lt;p&gt;In the async Rust ecosystem there exists a popular variation of an async
iterator trait called &lt;code&gt;Stream&lt;&#x2F;code&gt;. Rather than keeping the state of the iterator
(&lt;code&gt;self&lt;&#x2F;code&gt;) and the &lt;code&gt;next&lt;&#x2F;code&gt; function separate, it combines both into a single state.
The trait has a single method &lt;code&gt;poll_next&lt;&#x2F;code&gt; which acts as a mix between
&lt;code&gt;Future::poll&lt;&#x2F;code&gt; and &lt;code&gt;Iterator::next&lt;&#x2F;code&gt;. With a provided convenience function &lt;code&gt;async fn next&lt;&#x2F;code&gt; that is a thin wrapper around &lt;code&gt;poll_next&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;IntoStream {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;IntoStream: Stream&amp;lt;Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into_stream&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;IntoStream;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Stream {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll_next&lt;&#x2F;span&gt;&lt;span&gt;(                            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `fn poll_next`
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `Pin&amp;lt;&amp;amp;mut Self&amp;gt;`
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;,                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `task::Context`
&lt;&#x2F;span&gt;&lt;span&gt;    ) -&amp;gt; Poll&amp;lt;Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;&amp;gt;;           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `task::Poll` 
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `async`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;: Unpin                          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `Self: Unpin`
&lt;&#x2F;span&gt;&lt;span&gt;    { .. }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;size_hint&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;, Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) { ... }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;By combining both states into a single state, this trait violates one of the
core tenets of async Rust&#x27;s design: the ability to uniformly communicate
cancellation by dropping futures. Here if the future by &lt;code&gt;fn next&lt;&#x2F;code&gt; is dropped,
that is a no-op and cancellation will not occur. This causes compositional async
control-flow operators like &lt;code&gt;Future::race&lt;&#x2F;code&gt; to not work despite compiling.&lt;&#x2F;p&gt;
&lt;p&gt;To instead cancel the current call to &lt;code&gt;next&lt;&#x2F;code&gt; you are forced to either drop the
entire stream, or use some bespoke method to cancel just the future&#x27;s state.
Cancellation in async Rust is infamous for being hard to get right, which is
understandable when (among other things) core traits in the ecosystem do not
correctly handle it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;concurrent-iterator&quot;&gt;Concurrent Iterator&lt;&#x2F;h2&gt;
&lt;p&gt;As we&#x27;re approaching the end of our exposition here, let&#x27;s talk about the most
elaborate variations on &lt;code&gt;Iterator&lt;&#x2F;code&gt;. First in line: the &lt;code&gt;rayon&lt;&#x2F;code&gt; crate and the
&lt;code&gt;ParallelIterator&lt;&#x2F;code&gt; trait. Rayon provides what are called &quot;parallel iterators&quot;
which process items concurrently rather than sequentially, using operating
system threads. This tends to significantly improve throughput compared to
sequential processing, but have the caveat that all consumed items must
implement &lt;code&gt;Send&lt;&#x2F;code&gt;. To see just how familiar parallel iterators can be: the
following example looks almost identical to a sequential iterator except for the
call to &lt;code&gt;into_par_iter&lt;&#x2F;code&gt; instead of &lt;code&gt;into_iter&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;rayon::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_par_iter&lt;&#x2F;span&gt;&lt;span&gt;()   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Instead of calling `into_iter`.
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;for_each&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;| println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, x));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;ParallelIterator&lt;&#x2F;code&gt; trait however comes as a pair with the &lt;code&gt;Consumer&lt;&#x2F;code&gt; trait.
It can be a little mind-boggling but the way Rayon works is that combinators can
be chained to create a handler, which at the end of the chain is copied to each
thread and used there to handle items. This is of course a simplified
explanation; I&#x27;ll defer to Rayon maintainers to provide a detailed explanation.
To give you a sense how different these traits are from the regular
&lt;code&gt;Iterator&lt;&#x2F;code&gt;traits, here they are (simplified):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A consumer is effectively a generalized “fold” operation.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Consumer&amp;lt;Item&amp;gt;: Send + Sized {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The type of folder that this consumer can be converted into.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Folder: Folder&amp;lt;Item, Result = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Result&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The type of reducer that is produced if this consumer is split.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Reducer: Reducer&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Result&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The type of result that this consumer will ultimately produce.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Result: Send;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A type that can be iterated over in parallel
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;IntoParallelIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; What kind of iterator are we returning?
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Iter: ParallelIterator&amp;lt;Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; What type of item are we yielding?
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item: Send;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Return a stateful parallel iterator.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into_par_iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Iter;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Parallel version of the standard iterator trait.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;ParallelIterator: Sized + Send {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The type of item that this parallel iterator produces.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item: Send;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Internal method used to define the behavior of this
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; parallel iterator. You should not need to call this
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; directly.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;drive_unindexed&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;C&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;consumer&lt;&#x2F;span&gt;&lt;span&gt;: C) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;C::&lt;&#x2F;span&gt;&lt;span&gt;Result
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;        C: UnindexedConsumer&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What matters most here is that &lt;em&gt;using&lt;&#x2F;em&gt; the &lt;code&gt;ParallelIterator&lt;&#x2F;code&gt; trait feels
similar to a regular iterator. All you need to do is call &lt;code&gt;into_par_iter&lt;&#x2F;code&gt;
instead of &lt;code&gt;into_iter&lt;&#x2F;code&gt; and you&#x27;re off to the races. On the consuming side it
seems like we should be able to author some variation of &lt;code&gt;for..in&lt;&#x2F;code&gt; to consume
parallel iterators. Rather than speculate about syntax, we can look at the
signature of &lt;code&gt;ParallelIterator::for_each&lt;&#x2F;code&gt; to see which guarantees this would
need to make.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;for_each&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;F&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;: F)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    F: Fn(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item) + Sync + Send
&lt;&#x2F;span&gt;&lt;span&gt;{ .. }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can observe three changes here from the base iterator trait:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Self&lt;&#x2F;code&gt; no longer needs to be &lt;code&gt;Sized&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Somewhat predictably the closure &lt;code&gt;F&lt;&#x2F;code&gt; needs to be thread-safe.&lt;&#x2F;li&gt;
&lt;li&gt;The closure &lt;code&gt;F&lt;&#x2F;code&gt; needs to implement &lt;code&gt;Fn&lt;&#x2F;code&gt; rather than &lt;code&gt;FnMut&lt;&#x2F;code&gt; to prevent data races.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;We can then infer that in the case of a parallel &lt;code&gt;for..in&lt;&#x2F;code&gt; expression, the loop
body would not be able to close over any mutable references. This is an addition
to the existing limitation that loop bodies already can&#x27;t express &lt;code&gt;FnOnce&lt;&#x2F;code&gt;
semantics and move values (e.g. &lt;em&gt;&quot;Warning: this value was moved in a previous
iteration of the loop&quot;&lt;&#x2F;em&gt;.)&lt;&#x2F;p&gt;
&lt;p&gt;An interesting combination of are &quot;parallel iteration&quot; and &quot;async iteration&quot;.
An interesting aspect of the &lt;code&gt;async&lt;&#x2F;code&gt; keyword in Rust is that it allows for
ad-hoc concurrent execution of futures without needing to rely on special
syscalls or OS threads. This means that concurrency and parallelism can be
detached from one another. While we haven&#x27;t yet seen a &quot;parallel async iterator&quot;
trait in the ecosystem, the &lt;code&gt;futures-concurrency&lt;&#x2F;code&gt; crate does encode a
&quot;concurrent async iterator&quot; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#concurrent-stream&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Just like &lt;code&gt;ParallelIterator&lt;&#x2F;code&gt;,
&lt;code&gt;ConcurrentAsyncIterator&lt;&#x2F;code&gt; comes in a pair with a &lt;code&gt;Consumer&lt;&#x2F;code&gt;trait.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;concurrent-stream&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;Technically this trait is called &lt;code&gt;ConcurrentStream&lt;&#x2F;code&gt;, but there is little that is &lt;code&gt;Stream&lt;&#x2F;code&gt;-dependent here. I called it that because it is compatible with the &lt;code&gt;futures_core::Stream&lt;&#x2F;code&gt; trait since &lt;code&gt;futures-concurrency&lt;&#x2F;code&gt; is intended to be a production crate.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Describes a type which can receive data.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Consumer&amp;lt;Item, Fut&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    Fut: Future&amp;lt;Output = Item&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; What is the type of the item we’re returning when completed?
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Send an item down to the next step in the processing queue.
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fut&lt;&#x2F;span&gt;&lt;span&gt;: Fut) -&amp;gt; ConsumerState;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Make progress on the consumer while doing something else.
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;progress&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) -&amp;gt; ConsumerState;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; We have no more data left to send to the `Consumer`;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; wait for its output.
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;flush&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;IntoConcurrentAsyncIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;IntoConcurrentAsyncIter: ConcurrentAsyncIterator&amp;lt;Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into_co_iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;IntoConcurrentAsyncIter;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;ConcurrentAsyncIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Future: Future&amp;lt;Output = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Internal method used to define the behavior
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; of this concurrent iterator. You should not
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; need to call this directly.
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;drive&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;C&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;consumer&lt;&#x2F;span&gt;&lt;span&gt;: C) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;C::&lt;&#x2F;span&gt;&lt;span&gt;Output
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;        C: Consumer&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Future&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While &lt;code&gt;ParallelIterator&lt;&#x2F;code&gt; and &lt;code&gt;ConcurrentAsyncIterator&lt;&#x2F;code&gt; have similarities in both
usage and design, they are different enough that we cant quite think as one
being the async, non-thread-safe version of the other. Perhaps it is possible to
bring both traits closer to one another, so that the only difference are a few
strategically placed &lt;code&gt;async&lt;&#x2F;code&gt; keywords, but more research is needed to validate
whether that is possible.&lt;&#x2F;p&gt;
&lt;p&gt;Another interesting bit to point out here: concurrent iteration is also mutually
exclusive with lending iteration. A lending iterator relies on yielded items
having sequential lifetimes, while concurrent lifetimes rely on yielded items
having overlapping lifetimes. Those are fundamentally incompatible concepts.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;And that&#x27;s every iterator variant that I know of, bringing us to 17 different
variations. If we take away the variants that we can express using subtraits (4
variants) and auto-traits (5 variants), we are left with 9 different variants.
That&#x27;s 9 variants, with 76 methods, and approximately 150 trait impls in the
stdlib. That is a big API surface, and that&#x27;s not even considering all the
different combinations of iterators.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Iterator&lt;&#x2F;code&gt; is probably the single-most complex trait in the language. It is a
junction in the language where every effect, auto-trait, and lifetime feature
ends up intersecting. And unlike similar junctions like the &lt;code&gt;Fn&lt;&#x2F;code&gt;-family of
traits; the &lt;code&gt;Iterator&lt;&#x2F;code&gt; trait is stable, broadly used, and has a lot of
combinators. Meaning it both has a broad scope, and stringent
backwards-compatibility guarantees we need to maintain.&lt;&#x2F;p&gt;
&lt;p&gt;At the same time &lt;code&gt;Iterator&lt;&#x2F;code&gt; is also not that special either. It&#x27;s a pretty easy
trait to write by hand after all. The way I think of it is mainly as a canary for
language-wide shortcomings. &lt;code&gt;Iterator&lt;&#x2F;code&gt; is for example not unique in its
requirement for stable addresses: we want to be able to guarantee this for
arbitrary types and to be able to use this with arbitrary interfaces. I believe
that the question to ask here should be: what is stopping us from using
address-sensitive types with arbitrary types and arbitrary interfaces? If we can
answer that, not only will we have an answer for &lt;code&gt;Iterator&lt;&#x2F;code&gt; - we will have
solved it for all other interfaces we did not consciously anticipate would want
to interact with this &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#known-unknowns&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;known-unknowns&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;&#x2F;sup&gt;
&lt;p&gt;This is adjacent to &quot;known unknowns&quot; vs &quot;unknown unknowns&quot; - we should not just cater to cases we can anticipate, but also to cases we cannot. And that requires analyzing patterns and thinking in systems.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;In this post I&#x27;ve done my best to show by-example which limitations the
&lt;code&gt;Iterator&lt;&#x2F;code&gt; trait has today, and how each variant can overcome those. And while I
believe that we should try and lift those limitations over time, I don&#x27;t think
anyone is too keen on us minting 9 new variations on the &lt;code&gt;core::iter&lt;&#x2F;code&gt; submodule.
Nor the thousand-plus possible combinations of those submodules (yay
combinatorics). The only feasible approach I see to navigating the problem space
is by extending, rather than replacing, the &lt;code&gt;Iterator&lt;&#x2F;code&gt; trait. Here is my current
thinking for how we might be able to extend &lt;code&gt;Iterator&lt;&#x2F;code&gt; to support all iterator
variants:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;base trait&lt;&#x2F;strong&gt;: default, already supported&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;dyn-compatible&lt;&#x2F;strong&gt;: default, already supported&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;bounded&lt;&#x2F;strong&gt;: sub-trait, already supported&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;fused&lt;&#x2F;strong&gt;: sub-trait, already supported&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;thread-safe&lt;&#x2F;strong&gt;: auto-trait, already supported&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;seeking&lt;&#x2F;strong&gt;: sub-trait&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;compile-time&lt;&#x2F;strong&gt;: effect polymorphism (&lt;code&gt;const&lt;&#x2F;code&gt;) &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#const-effect&quot;&gt;9&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;lending&lt;&#x2F;strong&gt;: &lt;code&gt;&#x27;move&lt;&#x2F;code&gt; lifetime &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#move-lifetime&quot;&gt;10&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;with return value&lt;&#x2F;strong&gt;: unsure &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#unsure&quot;&gt;11&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;with next argument&lt;&#x2F;strong&gt;: default value + optional&#x2F;variadic arg&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;short-circuiting&lt;&#x2F;strong&gt;: effect polymorphism (&lt;code&gt;try&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;address-sensitive&lt;&#x2F;strong&gt;: auto-trait&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;guaranteeing destruct&lt;&#x2F;strong&gt;: auto-trait&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;async&lt;&#x2F;strong&gt;: effect polymorphism (&lt;code&gt;async&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;concurrent&lt;&#x2F;strong&gt;: new trait variant(s)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;const-effect&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;9&lt;&#x2F;sup&gt;
&lt;p&gt;the &lt;code&gt;const&lt;&#x2F;code&gt; effect itself is already polymorphic over the comptime effect, since &lt;code&gt;const fn&lt;&#x2F;code&gt; means: &quot;a function that can be executed either at comptime or runtime&quot;. Out of all the effect variants, &lt;code&gt;const&lt;&#x2F;code&gt; is most likely to happen in the near-term.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;move-lifetime&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;10&lt;&#x2F;sup&gt;
&lt;p&gt;What we want to express is that we have an associated type which MAY take a lifetime, not MUST take a lifetime. That way we can pass a type by value where a type would otherwise be expected to be passed by-reference. This is different from both &lt;code&gt;&#x27;static&lt;&#x2F;code&gt; lifetimes and &lt;code&gt;&amp;amp;own&lt;&#x2F;code&gt; references.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;unsure&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;11&lt;&#x2F;sup&gt;
&lt;p&gt;I tried answering how to add return values to the &lt;code&gt;Iterator&lt;&#x2F;code&gt; trait a year ago in my post &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;iterator-as-an-alias&#x2F;&quot;&gt;Iterator as an Alias&lt;&#x2F;a&gt;, but I came up short. As I mentioned earlier in the post: combining &quot;return with value&quot; and &quot;may short-circuit with error&quot; seems tricky. Maybe there is a combination here I&#x27;m missing &#x2F; we can special-case something. But I haven&#x27;t seen it yet.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;When evolving the language, I believe we entire job is to balance feature
development with the management of complexity. If done right, over time the
language should not only become more capable, but also simpler and easier to
extend. To quote something TC (T-Lang) said in a recent conversation: &quot;We should
get better at getting better every year&quot;. &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#mathematician&quot;&gt;12&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As we think about how we wish to overcome the challenges presented by this post,
it is my sincere hope that we will increasingly start thinking of ways to solve
classes of problems that just happen to show up with &lt;code&gt;Iterator&lt;&#x2F;code&gt; first. While at
the same time looking for opportunities to ship features sooner, without
blocking ourselves on supporting all of the use cases straight away.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;mathematician&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;12&lt;&#x2F;sup&gt;
&lt;p&gt;I recently remarked to TC that I&#x27;ve started to think about governance and language evolution as being about the derivative of the language and project. Rather than measuring the direct outcomes, we measure the process that produces those outcomes. TC remarked that what we should really care about is the double derivative. Not only should we improve our outcomes over time; the processes that produce those outcomes should improve over time as well. Or put differently: we should get better at getting better every year! I love this quote and I wanted y&#x27;all to read it too.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</description>
        </item>
        <item>
            <title>Musings on iterator trait names</title>
            <pubDate>Mon, 20 Jan 2025 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/musings-on-iterator-trait-names/</link>
            <guid>https://blog.yoshuawuyts.com/musings-on-iterator-trait-names/</guid>
            <description>&lt;p&gt;At the end of my &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;gen-auto-trait-problem&#x2F;&quot;&gt;last
post&lt;&#x2F;a&gt; I mentioned that one
of the main issues with the &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; trait is that it’s kind of a pain to
write. I wasn’t around when it was first introduced, but it’s not hard to tell
that the original authors intended for &lt;code&gt;Iterator&lt;&#x2F;code&gt; to be the primary interface
with &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; being an additional convenience.&lt;&#x2F;p&gt;
&lt;p&gt;This didn’t quite turn out to be the case though, and it’s common practice to
use &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; in both bounds and impls. &lt;del&gt;In the Rust 2024 edition we’re
changing Rust’s range type to implement &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; rather than &lt;code&gt;Iterator&lt;&#x2F;code&gt;.&lt;&#x2F;del&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#edition&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
And for example in Swift the equivalent trait to &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; (&lt;code&gt;Sequence&lt;&#x2F;code&gt;) is
the primary interface used for iteration. With the interface equivalent to
&lt;code&gt;Iterator&lt;&#x2F;code&gt; (&lt;code&gt;IteratorProtocol&lt;&#x2F;code&gt;) having a much harder to use name.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;edition&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Thanks to Lukas Wirth for pointing out that the range type change
didn&#x27;t end up making the cut for the edition. It&#x27;s been a couple of months since
I checked, and it seems it was removed for this edition. My understanding is
that this change is still desired, and might make it in for a future edition.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;So if not &lt;code&gt;Iterator&lt;&#x2F;code&gt;, what name could we use? Well, recently I wrote a
little library called &lt;code&gt;Iterate&lt;&#x2F;code&gt; that tries to answer that question. Let me walk
you through it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Note: this post is intended to be a public exploration, not a concrete
proposal. It&#x27;s a starting point, asking: &quot;... what if?&quot; I&#x27;m a firm advocate for
sharing ideas in public, especially if they&#x27;re not yet fully fleshed out. There
are a lot of good reasons to do that, but above all else: I think it&#x27;s fun!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;verbs-nouns-and-traits&quot;&gt;verbs, nouns, and traits&lt;&#x2F;h2&gt;
&lt;p&gt;In Rust most interfaces use verbs as their names. To read bytes from a stream
you use the trait named &lt;code&gt;Read&lt;&#x2F;code&gt;. To write bytes you use &lt;code&gt;Write&lt;&#x2F;code&gt;. To debug
something you use &lt;code&gt;Debug&lt;&#x2F;code&gt;. And to calculate numbers you can use &lt;code&gt;Add&lt;&#x2F;code&gt;, &lt;code&gt;Mul&lt;&#x2F;code&gt;
(multiply), or &lt;code&gt;Sub&lt;&#x2F;code&gt; (subtract). Most traits in the Rust stdlib are used to
perform concrete operations with, and the convention is to use verbs for that.&lt;&#x2F;p&gt;
&lt;p&gt;The stdlib does have one particularly interesting pairing in the form of &lt;code&gt;Hash&lt;&#x2F;code&gt;
(verb) and &lt;code&gt;Hasher&lt;&#x2F;code&gt; (noun). From the documentation: &quot;Types implementing &lt;code&gt;Hash&lt;&#x2F;code&gt;
are able to be hashed with an instance of &lt;code&gt;Hasher&lt;&#x2F;code&gt;.&quot; Or put differently: the
trait &lt;code&gt;Hash&lt;&#x2F;code&gt; represents the &lt;em&gt;operation&lt;&#x2F;em&gt; and the trait &lt;code&gt;Hasher&lt;&#x2F;code&gt; represents the
&lt;em&gt;state&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A hashable type.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Hash {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;hash&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;H: Hasher&amp;gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;state&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; H);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Represents state that is changed while hashing data.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Hasher {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;finish&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;bytes&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;a-verb-for-iteration&quot;&gt;A verb for iteration&lt;&#x2F;h2&gt;
&lt;p&gt;What the trait &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; really represents is: &quot;An iterable type&quot;. And the
trait &lt;code&gt;Iterator&lt;&#x2F;code&gt; can be reasonably described as: &quot;The state that is changed
while iterating over items&quot;. The verb&#x2F;noun split present in &lt;code&gt;Hash&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;Hasher&lt;&#x2F;code&gt;
feels like it easily applies to iteration too.&lt;&#x2F;p&gt;
&lt;p&gt;If &lt;code&gt;Iterator&lt;&#x2F;code&gt; is the noun that represents the iteration state, what is the verb
that represents the capability? The obvious choice would be &lt;code&gt;Iterate&lt;&#x2F;code&gt;. Which I
think ends up working out somewhat nicely. To iterate over items you implement
&lt;code&gt;Iterate&lt;&#x2F;code&gt;, which provides you with a stateful &lt;code&gt;Iterator&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; An iterable type.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Iterate {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Iterator: Iterator&amp;lt;Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;iterate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Iterator;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Represents state that is changed while iterating.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Iterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With our goal to make &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; less jarring to use in interfaces, the name
&lt;code&gt;Iterate&lt;&#x2F;code&gt; doesn&#x27;t seem half-bad. And it neatly follows the existing verb&#x2F;noun
split pairing we&#x27;re already using elsewhere in the stdlib.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;collecting-items&quot;&gt;Collecting items&lt;&#x2F;h2&gt;
&lt;p&gt;People familiar with Rust&#x27;s stdlib will be quick to note that &lt;code&gt;Iterator&lt;&#x2F;code&gt; and
&lt;code&gt;IntoIterator&lt;&#x2F;code&gt; are not the only iteration traits in use. We also have
&lt;code&gt;FromIterator&lt;&#x2F;code&gt; that functions as the inverse of &lt;code&gt;IntoIterator&lt;&#x2F;code&gt;. Where one exists
to convert types to iterators, the other exists to convert iterators back to
types. The latter is typically used via the &lt;code&gt;Iterator::collect&lt;&#x2F;code&gt; function.&lt;&#x2F;p&gt;
&lt;p&gt;But &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; has a less-known but equally useful sibling: &lt;code&gt;Extend&lt;&#x2F;code&gt;. Where
&lt;code&gt;IntoIterator&lt;&#x2F;code&gt; collects items into new instances of types, the &lt;code&gt;Extend&lt;&#x2F;code&gt; trait is
used to collect items into existing instances of types. It would feel pretty
weird to rename &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; to &lt;code&gt;Iterate&lt;&#x2F;code&gt;, but then keep &lt;code&gt;FromIterator&lt;&#x2F;code&gt; as-is.
What if instead of anchoring &lt;code&gt;FromIterator&lt;&#x2F;code&gt; as a dual to &lt;code&gt;IntoIterator&lt;&#x2F;code&gt;, we
instead treated it as a sibling to &lt;code&gt;Extend&lt;&#x2F;code&gt;. The obvious verb for this would be
&lt;code&gt;Collect&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Creates a collection with the contents of an iterator.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Collect&amp;lt;A&amp;gt;: Sized {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;: T) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;        T: Iterate&amp;lt;Item = A&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s interesting to note that the type &lt;code&gt;T&lt;&#x2F;code&gt; in &lt;code&gt;FromIterator&lt;&#x2F;code&gt; is bound by
&lt;code&gt;IntoIterator&lt;&#x2F;code&gt; rather than &lt;code&gt;Iterator&lt;&#x2F;code&gt;. Being able to use &lt;code&gt;T: Iterate&lt;&#x2F;code&gt; as a bound
here definitely feels a little nicer. And speaking of nicer: this would also
make the provided &lt;code&gt;Iterator::collect&lt;&#x2F;code&gt; and &lt;code&gt;Iterator::collect_into&lt;&#x2F;code&gt; methods feel
a little better:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Represents state that is changed while iterating.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Iterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Create a collection with the contents of this iterator.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;C&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; C
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;        C: Collect&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;: Sized,
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Extend a collection with the contents of this iterator.
&lt;&#x2F;span&gt;&lt;span&gt;    fn collect_into&amp;lt;E&amp;gt;(self, collection: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; E) -&amp;gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; E
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;        E: Extend&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;: Sized;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I don&#x27;t think this looks half-bad. And honestly: it might also be more
consistent overall, as traits representing other effects don&#x27;t have an
equivalent to &lt;code&gt;FromIterator&lt;&#x2F;code&gt;. The &lt;code&gt;Future&lt;&#x2F;code&gt; trait only has &lt;code&gt;IntoFuture&lt;&#x2F;code&gt;, and
variations on that in the ecosystem like
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-concurrency&#x2F;latest&#x2F;futures_concurrency&#x2F;future&#x2F;trait.Race.html&quot;&gt;&lt;code&gt;Race&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
No longer having a trait called &lt;code&gt;FromIterator&lt;&#x2F;code&gt; would help remove some confusion.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;async&quot;&gt;Async&lt;&#x2F;h2&gt;
&lt;p&gt;I guess we&#x27;ve broached the async topic now, so I guess we might as well keep
going. We added the trait &lt;code&gt;IntoFuture&lt;&#x2F;code&gt; to Rust in 2022 because we wanted an
equivalent to &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; but for the async effect. You can find some
motivating use cases for this in my &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-finalizers&#x2F;&quot;&gt;async builders
(2019)&lt;&#x2F;a&gt; post. We chose the name
&lt;code&gt;IntoFuture&lt;&#x2F;code&gt; because it matched the existing convention set by
&lt;code&gt;IntoIterator&#x2F;Iterator&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We already have &lt;code&gt;Try&lt;&#x2F;code&gt; for fallibility, we just discussed using &lt;code&gt;Iterate&lt;&#x2F;code&gt; for
iteration, what would the verb-based trait name be for asynchrony? The obvious
choice would be something like &lt;code&gt;Await&lt;&#x2F;code&gt;, as that is the name of the operation:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Await {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Future = Future&amp;lt;Output = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Future;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This however runs into one major limitation: &lt;code&gt;await&lt;&#x2F;code&gt; is a reserved keyword,
which means we can&#x27;t use it as the name of the method. Which means I&#x27;m not
actually sure what this trait should be called. With iterators we&#x27;re lucky that
we don&#x27;t have any shortage of related words: &lt;code&gt;loop&lt;&#x2F;code&gt;, &lt;code&gt;iterate&lt;&#x2F;code&gt;, &lt;code&gt;generate&lt;&#x2F;code&gt;,
&lt;code&gt;while&lt;&#x2F;code&gt;, &lt;code&gt;sequence&lt;&#x2F;code&gt; and so on. With async we&#x27;re a little shorter on words. If
anyone has any good ideas for verbs to use here, I&#x27;d love to hear suggestions!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;TLDR: I really wouldn&#x27;t mind &lt;code&gt;Iterate&lt;&#x2F;code&gt; being the main interface name for
iteration in Rust. That seems like it would be a step up from writing
&lt;code&gt;IntoIterator&lt;&#x2F;code&gt; in bounds everywhere. Just by changing a name, without the need
for any special new language features.&lt;&#x2F;p&gt;
&lt;p&gt;Now for whether we should make this change:.. maybe? I honestly don&#x27;t know. It&#x27;s
not just a matter of introducing a simple trait alias either: the method names and
associated types are also different and we can&#x27;t alias those. And I&#x27;m not
particularly keen for Rust to start dabbling in additional trait hierarchies
here either. Iteration is complex enough as it is, more super-traits are not
going to make things any simpler here.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Renaming and aliasing the trait is not
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! enough, the method names and associated
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! type names would need to be aliased too.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Iterate { .. }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;IntoIterator = Iterate;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So I think the only way this rename would actually make sense to follow through
on is if the process to make changes like these would make that change easy. I
don&#x27;t believe it is today, but I definitely believe we should want it to become
easy in the future. It would be nice if we could freely rename traits, methods,
and maybe even types across editions without causing any breakage.&lt;&#x2F;p&gt;
&lt;p&gt;Either way though: I had a lot of fun writing this post. If you want to try the
&lt;code&gt;Iterate&lt;&#x2F;code&gt; trait yourself today to get a better feel for it - check out the
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;iterate-trait&#x2F;1.0.1&#x2F;iterate_trait&#x2F;&quot;&gt;&lt;code&gt;iterate-trait&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate. It
has everything I&#x27;ve described in this post, as well as iterator combinators like
&lt;code&gt;map&lt;&#x2F;code&gt;. Probably don&#x27;t use if for anything serious, but definitely go having fun
with it.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>The gen auto-trait problem</title>
            <pubDate>Mon, 13 Jan 2025 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/gen-auto-trait-problem/</link>
            <guid>https://blog.yoshuawuyts.com/gen-auto-trait-problem/</guid>
            <description>&lt;p&gt;One of the open questions surrounding the unstable &lt;code&gt;gen {}&lt;&#x2F;code&gt; feature is whether
it should return &lt;code&gt;Iterator&lt;&#x2F;code&gt; or &lt;code&gt;IntoIterator&lt;&#x2F;code&gt;. People have had a feeling there
might be good reasons for it to return &lt;code&gt;IntoIterator&lt;&#x2F;code&gt;, but couldn&#x27;t necessarily
articulate &lt;em&gt;why&lt;&#x2F;em&gt;. Which is why it was included in the &quot;unresolved questions&quot;
section on the gen blocks RFC.&lt;&#x2F;p&gt;
&lt;p&gt;Because I&#x27;d like to see &lt;code&gt;gen {}&lt;&#x2F;code&gt; blocks stabilize sooner, I figured it would be
worth spending some time looking into this question and see whether there are
any reasons to pick one over the other. And I have found what I believe to be a
fairly annoying issue with &lt;code&gt;gen&lt;&#x2F;code&gt; returning &lt;code&gt;Iterator &lt;&#x2F;code&gt; that I&#x27;ve started calling
the gen auto-trait problem. In this post I&#x27;ll walk through what this problem is,
as well as how &lt;code&gt;gen&lt;&#x2F;code&gt; returning &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; would prevent it. So without
further ado, let&#x27;s dive in!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;leaking-auto-traits-from-gen-bodies&quot;&gt;Leaking auto-traits from gen bodies&lt;&#x2F;h2&gt;
&lt;p&gt;The issue I&#x27;ve found has to do with auto-trait impls on reified &lt;code&gt;gen {}&lt;&#x2F;code&gt;
instances. Take the &lt;code&gt;thread::spawn&lt;&#x2F;code&gt; API: it takes a closure which returns a type
&lt;code&gt;T&lt;&#x2F;code&gt;. If you haven&#x27;t seen its definition before, here it is:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;F, T&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;: F) -&amp;gt; JoinHandle&amp;lt;T&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    F: FnOnce() -&amp;gt; T + Send + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    T: Send + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This signature states that the closure &lt;code&gt;F&lt;&#x2F;code&gt; and return type &lt;code&gt;T&lt;&#x2F;code&gt; must be &lt;code&gt;Send&lt;&#x2F;code&gt;.
But what it doesn&#x27;t state is that all local values created inside the closure
&lt;code&gt;F&lt;&#x2F;code&gt; must be &lt;code&gt;Send&lt;&#x2F;code&gt; too - which is common in the async world. Now let&#x27;s create an
iterator using a &lt;code&gt;gen {}&lt;&#x2F;code&gt; block that we try and send across threads. We can create an iterator that yields a single u32:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; iter = gen {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;yield&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now if we try and pass this to &lt;code&gt;thread::spawn&lt;&#x2F;code&gt;, there are no problems. Our
iterator implements &lt;code&gt;+ Send&lt;&#x2F;code&gt; and things will work as expected:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ✅ Ok
&lt;&#x2F;span&gt;&lt;span&gt;thread::spawn(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;|| {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; num in iter {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;println&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{num}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now to show you the problem, let&#x27;s try this again but this time with a &lt;code&gt;gen {}&lt;&#x2F;code&gt;
block that internally creates a &lt;code&gt;std::rc::Rc&lt;&#x2F;code&gt;. This type is &lt;code&gt;!Send&lt;&#x2F;code&gt;, which means
that any type that holds it will also be &lt;code&gt;!Send&lt;&#x2F;code&gt;. That means that &lt;code&gt;iter&lt;&#x2F;code&gt; in our
example here is now no longer thread-safe:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; iter = gen { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `-&amp;gt; impl Iterator + !Send`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; rc = Rc::new(...);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;yield&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    rc.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;do_something&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That means if we try and send it across threads we&#x27;ll get a compiler error:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ❌ cannot send a `!Send` type across threads
&lt;&#x2F;span&gt;&lt;span&gt;thread::spawn(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;|| {   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `iter` is moved
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; num in iter {     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `iter` is used
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;println&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{num}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And that right there is the problem. Even though iterators are lazy and the &lt;code&gt;Rc&lt;&#x2F;code&gt;
in our &lt;code&gt;gen {}&lt;&#x2F;code&gt; block isn&#x27;t actually constructed until iteration begins on the
new thread, the generator block needs to reserve space for it internally and so
it inherits the &lt;code&gt;!Send&lt;&#x2F;code&gt; restriction. This leads to incompatibilities where
locals defined entirely within &lt;code&gt;gen {}&lt;&#x2F;code&gt; itself end up affecting the
public-facing API. This ends up being very subtle and tricky to debug, unless
you&#x27;re already familiar with the generator desugaring.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;preventing-the-leakage&quot;&gt;Preventing the leakage&lt;&#x2F;h2&gt;
&lt;p&gt;Solving the gen&#x27;s auto-trait problem is not that hard. What we want is for the
&lt;code&gt;!Send&lt;&#x2F;code&gt; fields in the generator to not show up in the generated type until we
are ready to start iterating over it. That sounds a little scary, but in
practice all we have to do is for &lt;code&gt;gen {}&lt;&#x2F;code&gt; to start returning an &lt;code&gt;impl IntoIterator&lt;&#x2F;code&gt; rather than an &lt;code&gt;impl Iterator&lt;&#x2F;code&gt;. The actual &lt;code&gt;Iterator&lt;&#x2F;code&gt; will still be &lt;code&gt;!Send&lt;&#x2F;code&gt;, but our type &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; will be &lt;code&gt;Send&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; iter = gen { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `-&amp;gt; impl IntoIterator + Send`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; rc = Rc::new(...);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;yield&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    rc.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;do_something&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Since our value &lt;code&gt;iter&lt;&#x2F;code&gt; implements &lt;code&gt;Send&lt;&#x2F;code&gt; we can now happily pass it across
thread bounds. And our code continues to operate as expected, as &lt;code&gt;for..in&lt;&#x2F;code&gt;
operates on &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; which is implemented for all &lt;code&gt;Iterator&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ✅ Ok
&lt;&#x2F;span&gt;&lt;span&gt;thread::spawn(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;|| {   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `iter` is moved
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; num in iter {     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `iter` is used
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;println&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{num}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you think about it, from a theoretical perspective this makes a lot of sense
too. We can think of &lt;code&gt;for..in&lt;&#x2F;code&gt; as our way of handling the iteration effect,
which expects an &lt;code&gt;IntoIterator&lt;&#x2F;code&gt;. &lt;code&gt;gen {}&lt;&#x2F;code&gt; is the dual of that, used to create
new instances of the iteration effect. It&#x27;s not at all strange for it to return
the same trait that &lt;code&gt;for..in&lt;&#x2F;code&gt; expects. With the added bonus that it doesn&#x27;t leak auto-traits from impl bodies to the type&#x27;s signature.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-about-other-effects-and-auto-traits&quot;&gt;What about other effects and auto-traits?&lt;&#x2F;h2&gt;
&lt;p&gt;This issue primarily affects effects which make use of the &lt;em&gt;generator
transform&lt;&#x2F;em&gt;. That is: iteration and async. In theory I believe that, yes, &lt;code&gt;async {}&lt;&#x2F;code&gt; should probably return &lt;code&gt;IntoFuture&lt;&#x2F;code&gt; rather than &lt;code&gt;Future&lt;&#x2F;code&gt;. In WG Async we regularly see issues that have to do with auto-traits leaking from inside function bodies out into the type&#x27;s signatures. If &lt;code&gt;async&lt;&#x2F;code&gt; (2019) would have returned &lt;code&gt;IntoFuture&lt;&#x2F;code&gt; (2022) rather than &lt;code&gt;Future&lt;&#x2F;code&gt; (2019) that certainly seems like it could have helped. Though there would be a higher barrier to make that change today now that things are already stable.&lt;&#x2F;p&gt;
&lt;p&gt;On the trait side this doesn&#x27;t just affect &lt;code&gt;Send&lt;&#x2F;code&gt; either: it applies to all
auto-traits, present and future. Though &lt;code&gt;Send&lt;&#x2F;code&gt; is by far the most common trait
people will experience issues with today, to a lesser extent this also already
applies to &lt;code&gt;Sync&lt;&#x2F;code&gt;. And in the future possibly also auto-traits like
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;marker&#x2F;trait.Freeze.html&quot;&gt;&lt;code&gt;Freeze&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;linear-types-one-pager&#x2F;&quot;&gt;&lt;code&gt;Leak&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, and
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;self-referential-types&#x2F;&quot;&gt;&lt;code&gt;Move&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Though this
shouldn&#x27;t be the main motivator, preventing potential future issues is not
worthless either.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Admittedly the worst part of &lt;code&gt;gen {}&lt;&#x2F;code&gt; returning &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; is that the name
of the trait kind of sucks. &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; sounds auxiliary to &lt;code&gt;Iterator&lt;&#x2F;code&gt;, and
so it feels a little wrong to make it the thing we return from &lt;code&gt;gen {}&lt;&#x2F;code&gt;. But on top of that: that&#x27;s a lot of characters to write.&lt;&#x2F;p&gt;
&lt;p&gt;I wonder what would have happened if we&#x27;d taken an approach more similar to
Swift. Swift has
&lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;documentation&#x2F;swift&#x2F;sequence&#x2F;&quot;&gt;&lt;code&gt;Sequence&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which is
like Rust&#x27;s &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;documentation&#x2F;swift&#x2F;iteratorprotocol&#x2F;&quot;&gt;&lt;code&gt;IteratorProtocol&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
which is like Rust&#x27;s &lt;code&gt;Iterator&lt;&#x2F;code&gt;. The primary interface people are expected to
use is short and memorable. While the secondary interface isn&#x27;t meant to be
directly used, and so it has a much longer and less memorable name. As we&#x27;re
increasingly thinking of &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; as the primary interface for async
iteration, maybe we&#x27;ll want to revisit the trait naming scheme in the future.&lt;&#x2F;p&gt;
&lt;p&gt;In conclusion: it seems like a good idea to prevent auto-traits from leaking from
gen bodies when reified. This is the kind of issue that if we can prevent we
should prevent, as it can be both difficult to diagnose and annoying to work
around. Having auto-trait leakage be a non-issue for generator blocks seems
worthwhile.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>What are temporal and spatial memory safety?</title>
            <pubDate>Sun, 15 Dec 2024 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/temporal-spatial-memory-safety/</link>
            <guid>https://blog.yoshuawuyts.com/temporal-spatial-memory-safety/</guid>
            <description>&lt;p&gt;The lovely folks working on security over at Google have recently been writing
about &lt;a href=&quot;https:&#x2F;&#x2F;research.google&#x2F;pubs&#x2F;secure-by-design-googles-perspective-on-memory-safety&#x2F;&quot;&gt;&quot;temporal (memory)
safety&quot;&lt;&#x2F;a&gt;
and &lt;a href=&quot;https:&#x2F;&#x2F;security.googleblog.com&#x2F;2024&#x2F;11&#x2F;retrofitting-spatial-safety-to-hundreds.html&quot;&gt;&quot;spatial (memory)
safety&quot;&lt;&#x2F;a&gt;.
When I first saw these terms it took me a minute to figure out what they meant,
as searching for it online didn&#x27;t yield immediate answers. So I figured it might
be helpful to write it down for others to find:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Spatial memory safety:&lt;&#x2F;strong&gt; describes violations like out-of-bounds access. Say you have a vec of 10 items, it&#x27;s undefined behavior if you try and read from the memory location of the non-existent 11th item. You can think of these as violations that have to do with &lt;em&gt;memory regions&lt;&#x2F;em&gt; (space).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Temporal memory safety:&lt;&#x2F;strong&gt; describes violations like use-after-free. Say you have a type that has been de-initialized already (&quot;dropped&quot; in Rust), it&#x27;s undefined behavior to then try and read from any of its fields. You can think of these as violations that have to do with the &lt;em&gt;ordering of memory operations&lt;&#x2F;em&gt; (time).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;My only qualm with these terms is that I&#x27;ve occasionally seen people drop the
&quot;memory&quot; qualifier. I think this is part of what makes these terms confusing:
there are other many more safety properties &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#safety&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; involving layout or
ordering that can be modeled that don&#x27;t have anything to do with memory safety. Skimming the entries
on &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Temporal_logic&quot;&gt;Temporal Logic&lt;&#x2F;a&gt; or
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;TLA%2B&quot;&gt;TLA+&lt;&#x2F;a&gt; should make that clear enough &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#example&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;safety&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;When modeling, the term &quot;safety&quot; refers to the absence of a defined negative property. That&#x27;s in contrast to &quot;liveness&quot; which refers to the presence of a defined positive property. &lt;a href=&quot;https:&#x2F;&#x2F;hillelwayne.com&#x2F;post&#x2F;hyperproperties&#x2F;&quot;&gt;Read more&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;example&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;If you prefer a concrete example: imagine two concurrent writers to the same TCP socket speaking HTTP. Without careful coordination between the two this will lead to issues involving &lt;em&gt;ordering of operations&lt;&#x2F;em&gt; (temporal safety) that may lead to data loss, data corruption, and so on - but without ever involving involving any memory safety violations.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;My ask then is that when discussing spatial memory safety and temporal
memory safety to refer to them as such in full. Don&#x27;t try and shorten them by
dropping the &quot;memory&quot; qualifier. Because when discussing formally modeled
properties it certainly pays to be specific about what it is that you&#x27;re trying to
guarantee.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Why `Pin` is a part of trait signatures (and why that&#x27;s a problem)</title>
            <pubDate>Tue, 15 Oct 2024 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/why-pin/</link>
            <guid>https://blog.yoshuawuyts.com/why-pin/</guid>
            <description>&lt;p&gt;I&#x27;ve been wondering for a little while why the &lt;code&gt;Future::poll&lt;&#x2F;code&gt; methods takes
&lt;code&gt;self: Pin&amp;lt;&amp;amp;mut Self&amp;gt;&lt;&#x2F;code&gt; in its signature. I assumed there must have been a good
reason, but when I asked my fellow WG Async members nobody seemed to know off
hand why that was exactly. Or maybe they did, and I just had some trouble
following. Either way, I think I&#x27;ve figured it out, and I want to spell it out
for posterity so that others can follow too.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-pin-is-part-of-method-signatures&quot;&gt;Why &lt;code&gt;Pin&lt;&#x2F;code&gt; is part of method signatures&lt;&#x2F;h2&gt;
&lt;p&gt;Take for example a type &lt;code&gt;MyType&lt;&#x2F;code&gt; and a trait &lt;code&gt;MyTrait&lt;&#x2F;code&gt;. We can write an
implementation of &lt;code&gt;MyTrait&lt;&#x2F;code&gt; which is only available when &lt;code&gt;MyType&lt;&#x2F;code&gt; is pinned:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;MyTrait {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;my_method&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;MyType;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; MyTrait &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; MyType&amp;gt; {}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Inside of functions we can even write bounds for this. Shout out here to Eric
Holk who showed me that apparently the left-hand side of trait bounds
can contain arbitrary types - not only generics or even types that are part of
the function signature. I had no idea.&lt;&#x2F;p&gt;
&lt;p&gt;With that we can express that we&#x27;re taking some type &lt;code&gt;T&lt;&#x2F;code&gt; by-value, and once we
pin that value it will implement &lt;code&gt;MyTrait&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;my_function&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;input&lt;&#x2F;span&gt;&lt;span&gt;: T)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a mut&lt;&#x2F;span&gt;&lt;span&gt; T&amp;gt;: MyTrait,
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; pinned_input = pin!(input);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Inside of &lt;code&gt;MyTrait::my_method&lt;&#x2F;code&gt;, the type of &lt;code&gt;self&lt;&#x2F;code&gt; will be &lt;code&gt;&amp;amp;mut Pin&amp;lt;&amp;amp;mut Self&amp;gt;&lt;&#x2F;code&gt;. That&#x27;s not the same as the owned type &lt;code&gt;Pin&amp;lt;&amp;amp;mut Self&amp;gt;&lt;&#x2F;code&gt;, but luckily we
can convert that into an owned type by calling
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;pin&#x2F;struct.Pin.html#method.as_mut&quot;&gt;&lt;code&gt;Pin::as_mut&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
The docs contain a big explainer why it&#x27;s safe here to go from a mutable
reference to an owned instance, which intuitively goes against Rust&#x27;s ownership
rules.&lt;&#x2F;p&gt;
&lt;p&gt;But what happens now if rather than writing a generic type &lt;code&gt;T&lt;&#x2F;code&gt; with a &lt;code&gt;where&lt;&#x2F;code&gt;
clause, we instead want to use an impl trait in associated position (APIT). We
might want to write something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; how do we express those same bounds here?
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;my_function&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;input&lt;&#x2F;span&gt;&lt;span&gt;: impl ???) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; pinned_input = pin!(input);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But we have no way to express that exact bound. Unlike regular generics, APITs
can&#x27;t express the left-hand side of the bound (lvalue), they can only name the
right-hand side (rvalue). This becomes even more pronounced when we try and use
&lt;code&gt;impl Trait&lt;&#x2F;code&gt; in return position (RPTIT).&lt;&#x2F;p&gt;
&lt;p&gt;Take for example a function that returns some type &lt;code&gt;T&lt;&#x2F;code&gt;. Using concrete trait
bounds we can express that this returns a type which when pinned implements
&lt;code&gt;MyTrait&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;my_function&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt;() -&amp;gt; T
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a mut&lt;&#x2F;span&gt;&lt;span&gt; T&amp;gt;: MyTrait,
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    MyType {}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But if we then try and express that same function using RPTIT, we lose the
ability to express that bound. The only solution to express an &lt;code&gt;-&amp;gt; impl Trait&lt;&#x2F;code&gt;
which exposes functionality when it&#x27;s pinned, is to make &lt;code&gt;Pin&lt;&#x2F;code&gt; directly part of
the signature on the methods, and not implement the trait for a &lt;code&gt;Pin&amp;lt;&amp;amp;mut Type&amp;gt;&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;MyTrait {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;my_method&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) {} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← note the signature of self here
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;MyType;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;MyTrait &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;MyType {} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← no longer implemented for `Pin&amp;lt;&amp;amp;mut MyType&amp;gt;`
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And now all of a sudden we can express &lt;code&gt;-&amp;gt; impl MyTrait&lt;&#x2F;code&gt; whose methods can only
be called when &lt;code&gt;MyType&lt;&#x2F;code&gt; is pinned. With &lt;code&gt;Unpin&lt;&#x2F;code&gt; being the opt-out for types
where that is not the case.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;my_function&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; impl MyTrait { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Can be either pinned or not!
&lt;&#x2F;span&gt;&lt;span&gt;    MyType {}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;implications&quot;&gt;Implications&lt;&#x2F;h2&gt;
&lt;p&gt;Concretely what this means is that if you want to have a trait that wants to
work with pinned values and work with all language features like normal, you
have to use &lt;code&gt;self: Pin&amp;lt;&amp;amp;mut Self&amp;gt;&lt;&#x2F;code&gt; part of the method signature. Maybe that&#x27;s
not a big deal for new traits, but it has implications for every existing trait
in the stdlib.&lt;&#x2F;p&gt;
&lt;p&gt;Take for example the &lt;code&gt;Iterator&lt;&#x2F;code&gt; trait. We can&#x27;t just &lt;code&gt;impl Iterator for Pin&amp;lt;&amp;amp;mut T&amp;gt;&lt;&#x2F;code&gt; and expect RPTIT to work. Instead the expected route here seems like it
should be to introduce a new trait &lt;code&gt;PinnedIterator&lt;&#x2F;code&gt; that takes &lt;code&gt;self: Pin&amp;lt;&amp;amp;mut T&amp;gt;&lt;&#x2F;code&gt;. This is a backwards-incompatibility shared by all existing traits in the
stdlib except for &lt;code&gt;Future&lt;&#x2F;code&gt;, which already takes &lt;code&gt;self: Pin&amp;lt;&amp;amp;mut Self&amp;gt;&lt;&#x2F;code&gt;. That&#x27;s a
pretty big limitation, and something that&#x27;s worth factoring into discussions about the viability of &lt;code&gt;Pin&lt;&#x2F;code&gt; beyond &lt;code&gt;Future&lt;&#x2F;code&gt;. For &lt;code&gt;Iterator&lt;&#x2F;code&gt; it means we would want to mint at least the following variants:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; iterator
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Iterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; address-sensitive iterator
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;PinnedIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; self&amp;gt;) -&amp;gt; Option&amp;lt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To run through some more implications of this: if we want to Rust users to be
able to declare address-sensitive types in Rust, then the most likely path now
is a duplication of the traits in the &lt;code&gt;std::io&lt;&#x2F;code&gt; submodule taking a shape similar
to this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mod &lt;&#x2F;span&gt;&lt;span&gt;io {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Read { ... }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;PinnedRead { ... }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Write { ... }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;PinnedWrite { ... }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Seek { ... }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;PinnedSeek { ... }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;BufRead { ... }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;PinnedBufRead { ... }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Pinning, like &lt;code&gt;async&lt;&#x2F;code&gt; and &lt;code&gt;try&lt;&#x2F;code&gt;, is a combinatorial property of traits which leads to an exponential amount of duplication. Lucky for us duplicating traits is not the only possible
path we can take: some form of polymorphism for existing interfaces over &lt;code&gt;Pin&lt;&#x2F;code&gt; seems possible too - as long as we&#x27;re willing to change our formulation of it. Which was what lead me to formulate
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;self-referential-types&#x2F;&quot;&gt;my design for the &lt;code&gt;Move&lt;&#x2F;code&gt; auto-trait&lt;&#x2F;a&gt;, which is composable just like e.g. &lt;code&gt;Send&lt;&#x2F;code&gt; and &lt;code&gt;Sync&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I want to quickly shout out my fellow WG Async folks. We&#x27;ve been talking about
this a bunch, and it&#x27;s been helpful working through this. Even if it&#x27;s taken me a couple of months to actually get around to posting this. Any mistakes in this
post however are definitely my own.&lt;&#x2F;p&gt;
&lt;p&gt;In this post I mainly wanted to articulate why &lt;code&gt;Future&lt;&#x2F;code&gt; takes &lt;code&gt;self: Pin&amp;lt;&amp;amp;mut Self&amp;gt;&lt;&#x2F;code&gt; rather than &lt;code&gt;&amp;amp;mut self&lt;&#x2F;code&gt; and rely on &lt;code&gt;impl Future for Pin&amp;lt;&amp;amp;mut T&amp;gt;&lt;&#x2F;code&gt;. I
think I&#x27;ve found a good reason for that, and it has again to do with the left-
and right-hand side of bounds. For me this also confirms my hypothesis that any
design for generalized self-referential types needs to be able to capture the following:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The ability to mark a type as being immovable&lt;&#x2F;li&gt;
&lt;li&gt;The ability to transition types from being movable to immovable&lt;&#x2F;li&gt;
&lt;li&gt;The ability to construct immovable types in-place&lt;&#x2F;li&gt;
&lt;li&gt;The ability to extend existing interfaces with immovability&lt;&#x2F;li&gt;
&lt;li&gt;The ability to describe self-referential lifetimes&lt;&#x2F;li&gt;
&lt;li&gt;The ability to safely initialize self-references without &lt;code&gt;Option&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This post specifically covered the fourth requirement: the ability to extend
existing interfaces with immovability. Addressing that can take the form of duplication of
interfaces (e.g. &lt;code&gt;Iterator&lt;&#x2F;code&gt; vs &lt;code&gt;PinnedIterator&lt;&#x2F;code&gt;), or composition via
(auto-)traits (e.g. &lt;code&gt;Move&lt;&#x2F;code&gt;). Other methods might be possible too, and I would
encourage people with ideas to share them.&lt;&#x2F;p&gt;
&lt;p&gt;PoignardAzur has &lt;a href=&quot;https:&#x2F;&#x2F;poignardazur.github.io&#x2F;2024&#x2F;08&#x2F;16&#x2F;pinned-places&#x2F;&quot;&gt;independently
described&lt;&#x2F;a&gt; why and how
pinned types need to be able to be constructed in-place. Their post showed
examples of both the third and sixth requirements in the list. They introduced a
form of emplacement via the &lt;code&gt;-&amp;gt; pin Type&lt;&#x2F;code&gt; notation. This is similar to the more
general &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;self-referential-types&#x2F;#converting-into-immovable-types&quot;&gt;&lt;code&gt;-&amp;gt; super Type&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
notation I introduced in my post, which I adapted from Mara&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;blog.m-ou.se&#x2F;super-let&#x2F;&quot;&gt;&lt;code&gt;super let&lt;&#x2F;code&gt;
post&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I hope this post helps at least partially clarify why &lt;code&gt;Pin&lt;&#x2F;code&gt; needs to be
part of interfaces. As well as helped spell out some of the logical consequences
once we consider how it interacts with the stdlib&#x27;s strict
backwards-compatibility requirements. Because I believe we can and should do
better than duplicating entire interfaces over the axis of immovability.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Solving my RSI issues</title>
            <pubDate>Mon, 23 Sep 2024 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/solving-my-rsi-issues/</link>
            <guid>https://blog.yoshuawuyts.com/solving-my-rsi-issues/</guid>
            <description>&lt;p&gt;For the past decade I&#x27;ve struggled with wrist injuries on and off. It&#x27;s a common
occupational injury for us keyboard users, and after my most recent bout this
year I decided it was time to actually do something about it. Permanently. I
like systemic solutions - they tickle a good part of my brain. And I figured I
could apply some of that to my keyboard habits too.&lt;&#x2F;p&gt;
&lt;p&gt;In this post I want to share a little about what my journey to actually fix my
wrist issues. Not to be prescriptive for others, but to be descriptive about
what I&#x27;m doing. Perhaps it&#x27;ll be useful for others, but mainly because it&#x27;s fun
for me to talk about. I&#x27;ve been making little ASCII cheat sheets for myself, and
basically I just wanted to have an excuse to post them publicly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;breaking-up-writing-sessions&quot;&gt;Breaking up writing sessions&lt;&#x2F;h2&gt;
&lt;p&gt;The way I&#x27;ve dealt with my RSI issues for the past eight years is by taking
repeated breaks. I&#x27;ve done this using the &lt;a href=&quot;https:&#x2F;&#x2F;apps.apple.com&#x2F;us&#x2F;app&#x2F;time-out-break-reminders&#x2F;id402592703?mt=12&quot;&gt;Time Out
app&lt;&#x2F;a&gt;
on macOS, and &lt;a href=&quot;https:&#x2F;&#x2F;workrave.org&quot;&gt;Workrave&lt;&#x2F;a&gt; on Windows and Linux. Both
applications bring up a modal pop-up on a set schedule. I have it set to create
a short 30-second break every 10 minutes or so, and a 10-minute break every 50
minutes.&lt;&#x2F;p&gt;
&lt;p&gt;While this does not make typing itself any less strenuous, it does break up some
of the repetition - which ends up helping a lot. Taking breaks can be a little
frustrating though, as it can break up flow. But it&#x27;s better to have a lot of
small breaks than longer-lasting injuries. Shout out to Jacob Groundwater for
suggesting this back in 2016 - it&#x27;s helped me a lot over the years.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;mobility&quot;&gt;Mobility&lt;&#x2F;h2&gt;
&lt;p&gt;Another thing I&#x27;ve been doing is mobility issues, specifically for my wrist. I
worked with a physio from 2018 to 2020, and I have a stretch routine that helps
with flexibility and mobility. I have to admit I&#x27;ve not been keeping that up,
but as symptoms flare back up, it&#x27;s something that I know I can apply when
needed.&lt;&#x2F;p&gt;
&lt;p&gt;Where taking breaks helps break up the intensity of the strain, physical
exercises help both with symptom relief and building resiliency. It&#x27;s not
perfect, but it&#x27;s yet another thing I&#x27;ve found that helps me. I&#x27;m a little
hesitant to provide instructions since I&#x27;m not a physio myself though, and it&#x27;s
definitely possible to hurt yourself if you don&#x27;t do it right.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;choosing-a-keyboard-layout&quot;&gt;Choosing a keyboard layout&lt;&#x2F;h2&gt;
&lt;p&gt;I started taking regular breaks again in June this year, and it&#x27;s not helped me
as well as it did before. I assume it has something to do with being older now,
and recovery just taking longer than it used to. Though I learned how to
touch-type when I was in my early teens, I know that using QWERTY layouts aren&#x27;t
particularly good for you. It requires a lot of extra movement in fingers, which
leads to a lot of extra strain.&lt;&#x2F;p&gt;
&lt;p&gt;Because I hope to continue to use computers in some capacity for the next fifty
odd years, I figured re-learning something I only learned twenty years ago would
be well-worth it in the long run. So time to bite the bullet, and learn a new
layout. But which one?&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m lucky that many of my friends are incredibly &lt;del&gt;geeky&lt;&#x2F;del&gt;knowledgeable, and I
figured one of them would probably have a good suggestion for what to learn. A
quick check online suggested that &lt;a href=&quot;https:&#x2F;&#x2F;colemakmods.github.io&#x2F;mod-dh&#x2F;&quot;&gt;Colemak
Mod-DH&lt;&#x2F;a&gt; would probably be a good choice.
So I checked with my friend Sy Brand, who thought it was a good layout - but
they suggested something better: &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Apsu&#x2F;Canary&quot;&gt;Canary&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Canary is a fun little layout based on Colemak Mod-DH but optimizes for
something called &quot;rolls&quot;. In keyboard terminology a &quot;roll&quot; is a sequence of keys
you can type with one hand. A layout which has &quot;high rolls&quot; means it&#x27;s a layout
that has many of those sequences. Here is what the layout looks like on a
regular keyboard:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;w l y p k z x o u ; [ ] \
&lt;&#x2F;span&gt;&lt;span&gt; c r s t b f n e i a &amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;  j v d g q m h &#x2F; , .
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Rolls in QWERTY are fairly uncommon. But with Canary a lot of words incorporate
rolls. This might be easier to show rather than explain, so here are some words
that incorporate rolls on a QWERTY layout: &lt;code&gt;asimo&lt;&#x2F;code&gt;, &lt;code&gt;werk&lt;&#x2F;code&gt;, &lt;code&gt;wookie&lt;&#x2F;code&gt;. Do you
notice how typing those feels kind of flowy? Now imagine nearly all words feel
like that. Creating that feeling without causing strain is what the Canary
layout was specifically designed for.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;learning-a-new-keyboard-layout&quot;&gt;Learning a new keyboard layout&lt;&#x2F;h2&gt;
&lt;p&gt;Once I&#x27;d decided to switch to a new keyboard layout, there was a big &quot;draw the
rest of the owl&quot; step to actually being able to use it. When I was a kid my mom
paid for me to take after-school classes for a number of weeks to learn how to
touch-type. That was 20 years ago though, and I somehow doubt there are
in-person classes teaching the Canary layout. So what to do?&lt;&#x2F;p&gt;
&lt;p&gt;It turns out there are lots of great options now. I&#x27;ve been using
&lt;a href=&quot;https:&#x2F;&#x2F;www.keybr.com&quot;&gt;keybr.com&lt;&#x2F;a&gt; which is free to use, supports various
layouts in-browser, and provides different guided trainings to learn how to
touch-type with new layouts. I&#x27;ve been using it daily for the past six weeks,
and honestly it does everything I could hope for.&lt;&#x2F;p&gt;
&lt;p&gt;To complement keybr I&#x27;ve also started using &lt;a href=&quot;https:&#x2F;&#x2F;ranelpadon.github.io&#x2F;ngram-type&#x2F;&quot;&gt;ngram
type&lt;&#x2F;a&gt; which allows you to train
&quot;N-grams&quot;. These are sequences of characters which are often grouped together.
Those high rolls I was talking about earlier? N-grams are the sequences they
refer to.&lt;&#x2F;p&gt;
&lt;p&gt;Finally I&#x27;ve also occasionally been using &lt;a href=&quot;https:&#x2F;&#x2F;monkeytype.com&quot;&gt;monkeytype&lt;&#x2F;a&gt;
which is more focused on leaderboards and good looks. A lot of keyboard
influencers (they exist) use this to show off how well they can type or how
good their keyboard sounds. I haven&#x27;t found it particularly useful to learn new
layouts with, but it&#x27;s been fun to play with!&lt;&#x2F;p&gt;
&lt;p&gt;On QWERTY I can comfortably type around 90 words per minute (wpm). When learning
Canary it took me a few days to get to 10 wpm (unusable), two weeks to get to
20wpm (better, but still unusable) and about a month to get to 40 wpm (usable
but slow). I spent about 10 total hours in keybr, averaging about 30 mins of
training a day. I have no sense for whether that&#x27;s fast or slow, but I was
positively surprised that I could rebuild 20 years of muscle memory in a matter
of weeks, with a fairly modest time investment.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;using-vim-movements-on-a-new-layout&quot;&gt;Using vim movements on a new layout&lt;&#x2F;h2&gt;
&lt;p&gt;One thin I knew would be an issue and actually turned out to be an issue was
editing code on a new layout. I use vim bindings in all of my editors, and vim
motions are just part of me now. I asked Sy about how they switched over to a
new layout when they did and deal with this, and well, they didn&#x27;t. Good on them
for not using vim bindings; sucks to be me.&lt;&#x2F;p&gt;
&lt;p&gt;This turned out to be a bit of a stumbling block: while I don&#x27;t &lt;em&gt;exclusively&lt;&#x2F;em&gt;
write code, I do still write a lot of it. And that means that I need to be able
to move around an editor. I mean, I know there are other vim movements and I use
those too. But heck, not being able to use the base vim motions to navigate?
Yeah, I wasn&#x27;t going to give that up.&lt;&#x2F;p&gt;
&lt;p&gt;I looked into changing key bindings in VS Code, and tried figuring out what
others had done - and there didn&#x27;t seem to be any good solutions. Except one:
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;manna-harbour&#x2F;miryoku&quot;&gt;Miryoku&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;keyboard-layers&quot;&gt;Keyboard layers&lt;&#x2F;h2&gt;
&lt;p&gt;One of the issues with QWERTY is that you move around your fingers a lot, which
causes strain over time. Miryoku is one attempt to define a layout which
minimizes the amount of movement your fingers need to make. It&#x27;s based on two principles:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Each finger should at most ever switch one key over&lt;&#x2F;li&gt;
&lt;li&gt;The strongest fingers (thumbs, index fingers) should do the most work&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The way it achieves this is by defining an entire layout which can be accessed
from the base position. The entire system is layer-based (modal), with each
layer being accessible by pressing down a specific key with your thumb. Numbers,
symbols, and navigation each get their own layer. And by putting the arrow keys
on the position of the vim bindings, it makes it possible to restore vim-like
navigation just by pressing down a single key. Here is what the neutral (base)
layer looks like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;w l y p b     z f o u &amp;#39;      ¹esc   ⁴ret
&lt;&#x2F;span&gt;&lt;span&gt;c r s t g     m n e i a      ²spc   ⁵bsp
&lt;&#x2F;span&gt;&lt;span&gt;q j v d k     x h &#x2F; , .      ³tab   ⁶del
&lt;&#x2F;span&gt;&lt;span&gt;    ¹ ² ³     ⁴ ⁵ ⁶
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But once we press and hold the space key (key 2) with our thumb, we engage the
navigation layer and the arrow keys become available to us. It&#x27;s not quite the same position as with vim - but you can configure it that way if you like too. Here&#x27;s what it looks like by default:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;- - - - -     - - - - -
&lt;&#x2F;span&gt;&lt;span&gt;- - - - -     - ← ↓ ↑ →
&lt;&#x2F;span&gt;&lt;span&gt;- - - - -     - - - - -
&lt;&#x2F;span&gt;&lt;span&gt;    ◼︎ - -     - - -    
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I thought this was neat and probably the right solution, but I wasn&#x27;t sure how
to engage the thumb keys on a regular keyboard. The space bar is in the way, and
there is no thumb cluster for us to press. One solution is to shift your fingers
one row up, and remap the keyboard to use the XQCBNM keys as our thumb keys.
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;manna-harbour&#x2F;miryoku_kmonad&quot;&gt;miryoku_kmonad&lt;&#x2F;a&gt; is a software
package for macOS and Linux which allows you to do exactly that. But I tried and
failed to get that to work reliably (or well: I lacked the patience to finish
debugging it), so I went to find a different solution.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hardware&quot;&gt;Hardware&lt;&#x2F;h2&gt;
&lt;p&gt;So far my plan was to keep using my existing hardware. I like my 60% Vortex
Cypher keyboard, and I figured I&#x27;d start by switching keyboard layouts and see
how far I could get. I tried that and got stuck after a while - so I figured I
might as well commit to the bit and invest in hardware.&lt;&#x2F;p&gt;
&lt;p&gt;I ended up going picking up a pre-soldered &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pashutk&#x2F;chocofi&quot;&gt;Chocify
keyboard&lt;&#x2F;a&gt; from
&lt;a href=&quot;https:&#x2F;&#x2F;shop.beekeeb.com&#x2F;product&#x2F;presoldered-chocofi-split-keyboard&#x2F;&quot;&gt;Beekeeb&lt;&#x2F;a&gt;.
This is a 36-key split keyboard which comes with Miryoku pre-installed. I got
the bluetooth-based version with the screen which cost a little extra. I did
make a mistake by choosing the &quot;Choc Blue&quot; switches which are different from
Cherry MX blue switches, so I&#x27;ve got a new set of tactile switches coming in soon (Kaihl Sunset).&lt;&#x2F;p&gt;
&lt;p&gt;Custom keyboards are pretty involved, but well worth it. Some things I didn&#x27;t know before I got started but had to learn on the way:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;international shipping of batteries is difficult - if you need bespoke batteries for a hardware project in Europe, Amazon is actually one of the better options.&lt;&#x2F;li&gt;
&lt;li&gt;the Chocify board uses the nice!nano micro-controller. The way you flash this is by double-clicking a button that turns it into USB drive mode, and then you can just drag and drop new firmware on it from your computer&lt;&#x2F;li&gt;
&lt;li&gt;you can solder cables to connect them. Though you want to heat-shrink them
after. I didn&#x27;t actually end up doing this, but got help from my local coffee
shop with this hah (if you&#x27;re reading this: thanks Valdi!)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Picking up hardware was something I didn&#x27;t want to do unless strictly necessary -
but I think it was the right choice. I&#x27;ve recently also started experiencing
shoulder pain after long typing sessions, and I&#x27;ve noticed that having a split ergo keyboard actually helps a lot with that too.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m fairly confident this little 36-key keyboard I have is going to become my
new daily driver once I get the hang of it. And while that isn&#x27;t the case yet, that moment is creeping up on me soon.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;learning-a-new-keyboard-layout-again&quot;&gt;Learning a new keyboard layout (again)&lt;&#x2F;h2&gt;
&lt;p&gt;Oh before I close out, it turns out that the Canary keyboard layout comes in two
variants: staggered and ortho. I didn&#x27;t realize the two were different, so I
just pressed &quot;canary&quot; on keybr and started learning. It turns out that was the
staggered layout:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;w l y p k z x o u ; [ ] \
&lt;&#x2F;span&gt;&lt;span&gt; c r s t b f n e i a &amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;  j v d g q m h &#x2F; , .
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On a 30% keyboard that layout ends up looking like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;w l y p k     z x o u ; 
&lt;&#x2F;span&gt;&lt;span&gt;c r s t b     f n e i a
&lt;&#x2F;span&gt;&lt;span&gt;j v d g q     m h &#x2F; , .
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The layout the Canary authors designed for keyboards like this is the &quot;ortho&quot;
layout which looks like this. It&#x27;s very similar, but not the same:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;w l y p b     z f o u &amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;c r s t g     m n e i a
&lt;&#x2F;span&gt;&lt;span&gt;q j v d k     x h &#x2F; , .
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Oops, I should have paid more attention before I got started. Though in all
fairness: I did start learning Canary under the assumption I&#x27;d stick with my 60%
staggered keyboard. So it makes sense I didn&#x27;t immediately jump to the ortho
layout. Though I probably should have thought to start learning the ortho layout
as soon as I put in the hardware order - which was a few weeks ago now.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Now that I have my keyboard, have the firmware flashed and batteries installed,
this is where I&#x27;m currently at in my journey: re-learning to type on the Canary
Ortho layout. I think this is fine, because when switching to the Miryoku layout
I need to re-learn where all the symbols are, so it&#x27;s not like I can hit the
ground running on my new keyboard anyway.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m still waiting on my new key switches to arrive which should make typing on
my new keyboard a lot easier (45g rather than 20g actuation force - MX blues
have 50g actuation). But I can already tell that Canary + Miryoku + Chocify
causes a lot less strain on my hands than QWERTY does.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m not going to say that people should follow what I&#x27;m doing. I don&#x27;t know your
situation, and maybe just getting an ergo QWERTY keyboard or taking more breaks
might be enough for your needs. But for me? I&#x27;ve really enjoyed going down the
rabbit hole of learning a new keyboard layout, getting a new keyboard, and
picking up various things along the way.&lt;&#x2F;p&gt;
&lt;p&gt;So has all of this solved my RSI issues? No - I&#x27;m not yet daily driving my new
keyboard, so I&#x27;m not yet experiencing the benefits. But I can tell the difference in strain I
experience when I switch to the split keyboard and new keyboard layout. Now that nearly
everything is in place to switch over, I can&#x27;t wait to start daily driving it.
I&#x27;m definitely taking the most involved path to solving this, but I think that
this might actually be the answer to fully fix the source of my injuries.&lt;&#x2F;p&gt;
&lt;p&gt;This post was a little break from my usual writing about type systems and language
design. If you&#x27;d like to learn more about ergonomic keyboard layouts, I really enjoyed this talk by Mattia Dal Ben: &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=unMXQTSQEak&quot;&gt;34 keys is all you need: an ergonomic keyboard journey&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;solving-my-rsi-issues&#x2F;.&#x2F;practice.jpg&quot; alt=&quot;a split keyboard on a table with an ipad. There is a bunch of colorful furniture in the background&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Here&#x27;s what my keyboard practice looked like this morning. I think it&#x27;s cute.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Further simplifying self-referential types for Rust</title>
            <pubDate>Mon, 08 Jul 2024 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/self-referential-types-2/</link>
            <guid>https://blog.yoshuawuyts.com/self-referential-types-2/</guid>
            <description>&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;self-referential-types&#x2F;&quot;&gt;In my last post&lt;&#x2F;a&gt; I
discussed how we might be able to introduce ergonomic self-referential types (SRTs) to
Rust, mostly by introducing features we know we want in some form anyway. The
features listed were:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Some form of &lt;code&gt;&#x27;unsafe&lt;&#x2F;code&gt; and &lt;code&gt;&#x27;self&lt;&#x2F;code&gt; lifetimes.&lt;&#x2F;li&gt;
&lt;li&gt;A safe out-pointer notation for Rust (&lt;code&gt;super let&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;-&amp;gt; super Type&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;A way to introduce out-pointers without breaking backwards-compat.&lt;&#x2F;li&gt;
&lt;li&gt;A new &lt;code&gt;Move&lt;&#x2F;code&gt; auto-trait that can be used to mark types as immovable (&lt;code&gt;!Move&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;View types which make it possible to safely initialize self-referential types.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This post was received quite well, and I thought the discussion which followed
was quite interesting. I learned about a number of things that I think would
help refine the design further, and I thought it would be good to write it up.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;not-all-self-referential-types-are-move&quot;&gt;Not all self-referential types are &lt;code&gt;!Move&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Niko Matsakis pointed out that not all self-referential types are necessarily
&lt;code&gt;!Move&lt;&#x2F;code&gt;. For example: if the data being referenced is heap-allocated, then the
type doesn&#x27;t actually have to be &lt;code&gt;!Move&lt;&#x2F;code&gt;. When writing protocol parsers, it&#x27;s
actually fairly common to read data into a heap-allocated type first. It seems
likely that a fair number of self-referential types don&#x27;t actually also need to
be &lt;code&gt;!Move&lt;&#x2F;code&gt; or any concept of &lt;code&gt;Move&lt;&#x2F;code&gt; at all to function. Which also means we
don&#x27;t need some form of &lt;code&gt;super let&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;-&amp;gt; super Type&lt;&#x2F;code&gt; to construct types
in-place.&lt;&#x2F;p&gt;
&lt;p&gt;If we just want to enable self-references for heap-allocated types, then all we
need for that is a way to initialize them (view types) and an ability to
describe the self-lifetimes (&lt;code&gt;&#x27;unsafe&lt;&#x2F;code&gt; as a minimum). That should give us a good
idea of what we can prioritize to begin enabling a limited form of
self-references.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-self-lifetime-is-insufficient&quot;&gt;The &lt;code&gt;&#x27;self&lt;&#x2F;code&gt; lifetime is insufficient&lt;&#x2F;h2&gt;
&lt;p&gt;Speaking of lifetimes, &lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;1dsoaw2&#x2F;comment&#x2F;lb5hmpg&#x2F;&quot;&gt;Mattieum pointed
out&lt;&#x2F;a&gt; that
&lt;code&gt;&#x27;self&lt;&#x2F;code&gt; likely wasn&#x27;t going to be enough. &lt;code&gt;&#x27;self&lt;&#x2F;code&gt; points to an entire struct,
which ends up being too coarse to be practical. Instead we need to be able to
point to individual fields to describe lifetimes.&lt;&#x2F;p&gt;
&lt;p&gt;Apparently Niko has also come up with a feature for this, in the form of
&lt;a href=&quot;https:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2024&#x2F;06&#x2F;02&#x2F;the-borrow-checker-within&#x2F;#step-2-a-syntax-for-lifetimes-based-on-places&quot;&gt;lifetimes based on
places&lt;&#x2F;a&gt;.
Rather than having abstract lifetimes like the &lt;code&gt;&#x27;a&lt;&#x2F;code&gt; that we use to link to
values with, it would be nicer if references just always had implicit, unique
lifetime names. With access to that, we should rewrite the motivating example
from our last post from being based on &lt;code&gt;&#x27;self&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;GivePatsFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;resume_from&lt;&#x2F;span&gt;&lt;span&gt;: GivePatsState,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: Option&amp;lt;String&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: Option&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;self str&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Note the `&amp;#39;self` lifetime
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To instead be based on paths:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;GiveManyPatsFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;resume_from&lt;&#x2F;span&gt;&lt;span&gt;: GivePatsState,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;first&lt;&#x2F;span&gt;&lt;span&gt;: Option&amp;lt;String&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: Option&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;self&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;first &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Note the `&amp;#39;self.first` lifetime
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This might not seem like it&#x27;s that important in this example; but once we
introduce mutability things quickly spiral. And not introducing a magic &lt;code&gt;&#x27;self&lt;&#x2F;code&gt;
in favor of always requiring &lt;code&gt;&#x27;self.field&lt;&#x2F;code&gt; seems like it would generally be
better. And that requires having lifetimes which can be based on places, which
seems like a great idea regardless.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;automatic-referential-stability&quot;&gt;Automatic referential stability&lt;&#x2F;h2&gt;
&lt;p&gt;Earlier in this post we established that we don&#x27;t actually need to encode
&lt;code&gt;!Move&lt;&#x2F;code&gt; for self-referential types which store their values on the heap. That&#x27;s
not all self-referential types - but does describe a fair number of them. Now
what if we didn&#x27;t need to encode &lt;code&gt;!Move&lt;&#x2F;code&gt; for almost the entire remaining set of
self-referential types?&lt;&#x2F;p&gt;
&lt;p&gt;If that sounds like move constructors, you&#x27;d be right - but with a catch! Unlike
the &lt;code&gt;Relocate&lt;&#x2F;code&gt; trait I described in my last post, &lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;1dsoaw2&#x2F;comment&#x2F;lb4rw4g&#x2F;&quot;&gt;DoveOfHope
noted&lt;&#x2F;a&gt; that we
might not even need that to work. After all: if the compiler already knows that
we&#x27;re pointing to a field contained within the struct - can&#x27;t the compiler make
sure to update the pointers when we try and move the structure?&lt;&#x2F;p&gt;
&lt;p&gt;I was skeptical about the possibility of this until I read about place-based
lifetimes. With that it seems like we would actually have enough granularity to
know how to update which fields when they are moved. In terms of cost: that&#x27;s
just updating the value of a pointer on move - which is effectively free. And it
would rid us almost entirely of needing to encode &lt;code&gt;!Move&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The only cases not covered by this would be &lt;code&gt;&#x27;unsafe&lt;&#x2F;code&gt; references or actual
&lt;code&gt;*const T&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;*mut T&lt;&#x2F;code&gt; pointers to stack data. The compiler doesn&#x27;t actually know
what those point to, and so cannot update them on move. For that some form of
&lt;code&gt;Relocate&lt;&#x2F;code&gt; trait actually seems like it would be useful to have. But that&#x27;s
something that wouldn&#x27;t need to be added straight away either.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;raw-pointer-operations-and-automatic-referential-stability&quot;&gt;Raw pointer operations and automatic referential stability&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;This section was added after publication, on 2024-07-08.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;While it should be possible for the compiler to guarantee that the codegen is
correct for e.g. &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;mem&#x2F;fn.swap.html&quot;&gt;&lt;code&gt;mem::swap&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;,
we can&#x27;t make those same guarantees for raw pointer operations such as
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;ptr&#x2F;fn.swap.html&quot;&gt;&lt;code&gt;ptr::swap&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. And because
existing structures may be freely using those operations internally, that means
on-stack self-referential types can&#x27;t just be made to work without any caveats
the way we can for on-heap SRTs. That&#x27;s indeed a problem, and I want to thank
&lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;1dy6o8e&#x2F;comment&#x2F;lc6hs2j&quot;&gt;The_8472&lt;&#x2F;a&gt; for
pointing this out.&lt;&#x2F;p&gt;
&lt;p&gt;I was really hoping to be able to avoid extra bounds, so that on-stack SRTs
could match the experience of on-heap SRTs. But that doesn&#x27;t seem possible, so
perhaps some minimum amount of bounds which we can flip to being set by default
(like &lt;code&gt;Sized&lt;&#x2F;code&gt;) over an edition might be enough to do the trick here. I&#x27;m
currently thinking of something like:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Introduce a new auto marker trait &lt;code&gt;Transfer&lt;&#x2F;code&gt; to complement &lt;code&gt;Relocate&lt;&#x2F;code&gt;, as a dual
to Rust&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;marker&#x2F;trait.Destruct.html&quot;&gt;&lt;code&gt;Destruct&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
&#x2F; &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;ops&#x2F;trait.Drop.html&quot;&gt;&lt;code&gt;Drop&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; system. &lt;code&gt;Transfer&lt;&#x2F;code&gt;
is the name of the bound people would use, &lt;code&gt;Relocate&lt;&#x2F;code&gt; provides the hooks to
extend the &lt;code&gt;Transfer&lt;&#x2F;code&gt; system.&lt;&#x2F;li&gt;
&lt;li&gt;All types with &lt;code&gt;&#x27;self&lt;&#x2F;code&gt; lifetimes automatically implement &lt;code&gt;Transfer&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Only bounds which include &lt;code&gt;+ Transfer&lt;&#x2F;code&gt; can take &lt;code&gt;impl Transfer&lt;&#x2F;code&gt; types.&lt;&#x2F;li&gt;
&lt;li&gt;All relevant raw pointer move operations must uphold additional safety
invariants of what to do with &lt;code&gt;impl Transfer&lt;&#x2F;code&gt; types.&lt;&#x2F;li&gt;
&lt;li&gt;We gradually update the stdlib to support &lt;code&gt;+ Transfer&lt;&#x2F;code&gt; in all bounds.&lt;&#x2F;li&gt;
&lt;li&gt;Over some edition we make opt-out rather than opt-in (&lt;code&gt;T: Transfer&lt;&#x2F;code&gt; → &lt;code&gt;T: ?Transfer&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;auto &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Transfer {}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Relocate { ... }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I was really hoping we could avoid something like this. And it does put into
question whether this is actually simpler than immovable types. But the_8472 is
quite right that this is an issue, and so we need to address it. Luckily we&#x27;ve
already done something like this before with &lt;code&gt;const&lt;&#x2F;code&gt;. And I don&#x27;t think that
this is something we can generalize. I&#x27;ll write more about this at some later
date.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;relocate-should-probably-take-own-self&quot;&gt;&lt;code&gt;Relocate&lt;&#x2F;code&gt; should probably take &lt;code&gt;&amp;amp;own self&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Now, even if we don&#x27;t expect people to need to write their own pointer update
logic, basically like ever, it&#x27;s still something that should be provided. And
when we do, we should encode it correctly.  Nadrieril very helpfully pointed out
that the &lt;code&gt;&amp;amp;mut self&lt;&#x2F;code&gt; bound on the &lt;code&gt;Relocate&lt;&#x2F;code&gt; trait might not actually be what we
want - because we&#x27;re not just borrowing a value - we actually want to destruct
it. Instead they informed me about the work done towards &lt;code&gt;&amp;amp;own&lt;&#x2F;code&gt;, which would give access to something called: &quot;owned references&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Daniel Henry-Mantilla is the author of the &lt;a href=&quot;http:&#x2F;&#x2F;docs.rs&#x2F;stackbox&quot;&gt;&lt;code&gt;stackbox&lt;&#x2F;code&gt;
crate&lt;&#x2F;a&gt; as well as the main person responsible for the
lifetime extension system behind the &lt;code&gt;pin!&lt;&#x2F;code&gt; macro in the stdlib. A while back he
shared &lt;a href=&quot;https:&#x2F;&#x2F;internals.rust-lang.org&#x2F;t&#x2F;a-sketch-for-move-semantics&#x2F;18632&#x2F;19?u=illicitonion&quot;&gt;a very helpful writeup about
&lt;code&gt;&amp;amp;own&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
The core of the idea is that we should decouple the concepts of: &lt;em&gt;&quot;Where is the
data concretely stored?&quot;&lt;&#x2F;em&gt; from: &lt;em&gt;&quot;Who logically owns the data?&quot;&lt;&#x2F;em&gt; Resulting in
the idea of having a reference which doesn&#x27;t just provide &lt;em&gt;temporary&lt;&#x2F;em&gt; unique
access - but can take &lt;em&gt;permanent&lt;&#x2F;em&gt; unique access. In his post, Daniel helpfully
provides the following table:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;Semantics for &lt;code&gt;T&lt;&#x2F;code&gt;&lt;&#x2F;th&gt;&lt;th&gt;For the backing allocation&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;&amp;amp;T&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Shared access&lt;&#x2F;td&gt;&lt;td&gt;Borrowed&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;&amp;amp;mut T&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Exclusive access&lt;&#x2F;td&gt;&lt;td&gt;Borrowed&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;&amp;amp;own T&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Owned access  &lt;br&gt;(drop responsibility)&lt;&#x2F;td&gt;&lt;td&gt;Borrowed&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Applying this to our post, we would use this to change the trait &lt;code&gt;Relocate&lt;&#x2F;code&gt; from
taking &lt;code&gt;&amp;amp;mut self&lt;&#x2F;code&gt;, which temporarily takes exclusive access of a type - but
can&#x27;t actually drop the type:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Relocate {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;relocate&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; super &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To instead take &lt;code&gt;&amp;amp;own&lt;&#x2F;code&gt;, which takes permanent exclusive access of a type, and
can actually drop the type:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Relocate {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;relocate&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;own &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; super &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;edit 2024-07-08: This example was added later&lt;&#x2F;em&gt;. To explain what &lt;code&gt;&amp;amp;own&lt;&#x2F;code&gt; solves,
let&#x27;s take a look at the &lt;code&gt;Relocate&lt;&#x2F;code&gt; example impl from our last post. In it we
say the following:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;We&#x27;re making one sketchy assumption here: we need to be able to take the owned
data from self, without running into the issue where the data can&#x27;t be moved
because it is already borrowed from self.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: String,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;self str&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: String) -&amp;gt; super &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ ... }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Relocate &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;relocate&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; super &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; data = String::new();                   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← dummy type, does not allocate
&lt;&#x2F;span&gt;&lt;span&gt;        mem::swap(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.data, &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; data);           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← take owned data
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;super let&lt;&#x2F;span&gt;&lt;span&gt; cat = Cat { data };                   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← construct new instance
&lt;&#x2F;span&gt;&lt;span&gt;        cat.name = cat.data.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39; &amp;#39;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← create self-ref
&lt;&#x2F;span&gt;&lt;span&gt;        cat                                             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← return new instance
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What &lt;code&gt;&amp;amp;own&lt;&#x2F;code&gt; gives us is a way to correctly encode the semantics here. Because
the type is not moved we can&#x27;t actually move by-value. But logically we do still
want to claim unique ownership of the value so we can destruct the type and move
individual fields. That&#x27;s kind of the way moving &lt;code&gt;Box&lt;&#x2F;code&gt; by-value works too, but
rather than having the allocation on the heap, the allocation can be anywhere.
With that we could rewrite the rather sketchy &lt;code&gt;mem::swap&lt;&#x2F;code&gt; code above into more normal-looking destructuring + initialization instead:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: String,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;self str&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: String) -&amp;gt; super &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ ... }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Relocate &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;relocate&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; super &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let Self &lt;&#x2F;span&gt;&lt;span&gt;{ data, .. } = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;;                   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← destruct `self`
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;super let&lt;&#x2F;span&gt;&lt;span&gt; cat = Cat { data };                   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← construct new instance
&lt;&#x2F;span&gt;&lt;span&gt;        cat.name = cat.data.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39; &amp;#39;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← create self-ref
&lt;&#x2F;span&gt;&lt;span&gt;        cat                                             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← return new instance
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, because this actually does need to construct types in fixed memory
locations this trait would need to have some form of &lt;code&gt;-&amp;gt; super Self&lt;&#x2F;code&gt; syntax.
After all: this would be the one place where it would still be needed. For
anyone interested in keeping up to date with &lt;code&gt;&amp;amp;own&lt;&#x2F;code&gt;, here is &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;issues&#x2F;998&quot;&gt;the Rust issue for it&lt;&#x2F;a&gt; (which also happens to have
been filed by Niko).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;motivating-example-reworked-again&quot;&gt;Motivating example, reworked again&lt;&#x2F;h2&gt;
&lt;p&gt;With this in mind, we can rework the motivating example from the last post once
again. To refresh everyone&#x27;s memory, this is the high-level &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt;-based
Rust code we would:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;give_pats&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; data = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;chashu tuna&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; name = data.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39; &amp;#39;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;pat_cat&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;name).await;
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;patted &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{name}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;} 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;give_pats&lt;&#x2F;span&gt;&lt;span&gt;().await;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And using the updates in this post we can proceed to desugar it. This time
around without the need for any reference to &lt;code&gt;Move&lt;&#x2F;code&gt; or in-place construction,
thanks to path-based lifetimes and the compiler automatically preserving
referential stability:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;GivePatsState {
&lt;&#x2F;span&gt;&lt;span&gt;    Created,
&lt;&#x2F;span&gt;&lt;span&gt;    Suspend1,
&lt;&#x2F;span&gt;&lt;span&gt;    Complete,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;GivePatsFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;resume_from&lt;&#x2F;span&gt;&lt;span&gt;: GivePatsState,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: Option&amp;lt;String&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: Option&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;self&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;data &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Note the `&amp;#39;self.data` lifetime
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;GivePatsFuture {   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← No in-place construction needed
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            resume_from: GivePatsState::Created,
&lt;&#x2F;span&gt;&lt;span&gt;            data: None,
&lt;&#x2F;span&gt;&lt;span&gt;            name: None
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Future &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;GivePatsFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output = ();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;)  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← No `Pin` needed
&lt;&#x2F;span&gt;&lt;span&gt;        -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; { ... }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is significantly simpler than what we had before in its definition. And even the actual desugaring of the invocation ends up being simpler: no longer needing the intermediate &lt;code&gt;IntoFuture&lt;&#x2F;code&gt; constructor to guarantee in-place construction.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; into_future = GivePatsFuture::new();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; future = into_future.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_future&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← No `pin!` needed
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; future.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; current_context) {
&lt;&#x2F;span&gt;&lt;span&gt;        Poll::Ready(ready) =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt; ready,
&lt;&#x2F;span&gt;&lt;span&gt;        Poll::Pending =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;yield&lt;&#x2F;span&gt;&lt;span&gt; Poll::Pending,
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;All that&#x27;s needed for this is for the compiler to update the addresses of
self-pointers on move. That&#x27;s a little bit of extra codegen whenever a value is
moved - rather than just a bitwise copy, it also needs to update pointer values.
But it seems quite doable to implement, should actually perform really well, and
most importantly: users would rarely if ever need to think about it. Writing
&lt;code&gt;&amp;amp;&#x27;self.field&lt;&#x2F;code&gt; would always just work.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;when-immovable-types-are-still-needed&quot;&gt;When immovable types are still needed&lt;&#x2F;h2&gt;
&lt;p&gt;I don&#x27;t want to discount the idea of immovable types entirely though. There are
definitely benefits to having types which cannot be moved. Especially when
working with FFI structures that require immovability. Or some high-performance
data structures which use lots of self-references to stack-based data which
would be too expensive to update. Use cases certainly exist, but they&#x27;re going
to be fairly niche. For example: Rust for Linux uses immovable types for their
intrusive linked lists - and I think those probably need some form of
immovability to actually work.&lt;&#x2F;p&gt;
&lt;p&gt;However, if the compiler doesn&#x27;t require immovable types to provide
self-references, then immovable types suddenly go from being load-bearing to
instead becoming something closer to an optimization. It&#x27;s likely still worth
adding them since they certainly are more efficient. But if we do it right,
adding immovable types will be backwards-compatible, and would be something we
can introduce later as an optimization.&lt;&#x2F;p&gt;
&lt;p&gt;When it comes to whether &lt;code&gt;async {}&lt;&#x2F;code&gt; should return &lt;code&gt;impl Future&lt;&#x2F;code&gt; or &lt;code&gt;impl IntoFuture&lt;&#x2F;code&gt;: I think the answer really should be &lt;code&gt;impl IntoFuture&lt;&#x2F;code&gt;. In the 2024
edition we&#x27;re changing range syntax (&lt;code&gt;0..12&lt;&#x2F;code&gt;) from returning &lt;code&gt;Iterator&lt;&#x2F;code&gt; &lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rfcs&#x2F;3550-new-range.html&quot;&gt;to
returning &lt;code&gt;IntoIterator&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
This matches Swift&#x27;s behavior, where &lt;code&gt;0..12&lt;&#x2F;code&gt; returns
&lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;documentation&#x2F;swift&#x2F;sequence&quot;&gt;&lt;code&gt;Sequence&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; rather
than &lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;documentation&#x2F;swift&#x2F;iteratorprotocol&quot;&gt;&lt;code&gt;IteratorProtocol&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. I think this is a good indication that &lt;code&gt;async {}&lt;&#x2F;code&gt; and &lt;code&gt;gen {}&lt;&#x2F;code&gt; probably also should return &lt;code&gt;impl Into*&lt;&#x2F;code&gt;  traits rather than their respective traits.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I like it when something I write is discussed and I end up picking up on other
relevant work. I think to enable self-referential types I&#x27;m now definitely
favoring a form of built-in pointer updates as part of the language over
immovable types (edit: &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;self-referential-types-2&#x2F;#raw-pointer-operations-and-automatic-referential-stability&quot;&gt;maybe I spoke too soon&lt;&#x2F;a&gt;). However, if we do want immovable types - I think my last post
provides a coherent and user-friendly design to get us there.&lt;&#x2F;p&gt;
&lt;p&gt;There are a fairly large number of dependencies if we want to implement a
complete story for self-referential types. Luckily we can implement features one
at a time, enabling increasingly more expressive forms of self-referential
types. In terms of importance: some form of &lt;code&gt;&#x27;unsafe&lt;&#x2F;code&gt; seems like a good starting
point. Followed by place-based lifetimes. View types seem useful, but aren&#x27;t in
the critical path since we can work around phased initialization using an option
dance. Here&#x27;s a graph of all features and their dependencies.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;self-referential-types-2&#x2F;srt-dep-graph.jpg&quot; alt=&quot;A graph showing the various dependencies between language items&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Breaking down the features like has actually further reinforced my perception
that this all seems quite doable. &lt;code&gt;&#x27;unsafe&lt;&#x2F;code&gt; doesn&#x27;t seem like it&#x27;s that far out.
And Niko has sounded somewhat serious about path-based lifetimes and view types.
We&#x27;ll have to see how quickly those will actually end up being developed in
practice - but having laid this all out like this, I&#x27;m feeling somewhat
optimistic!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Ergonomic Self-Referential Types for Rust</title>
            <pubDate>Mon, 01 Jul 2024 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/self-referential-types/</link>
            <guid>https://blog.yoshuawuyts.com/self-referential-types/</guid>
            <description>&lt;p&gt;I&#x27;ve been thinking a little about self-referential types recently, and while
it&#x27;s &lt;em&gt;technically possible&lt;&#x2F;em&gt; to write them today using &lt;code&gt;Pin&lt;&#x2F;code&gt; (limits apply),
they&#x27;re not at all convenient. So what would it take to make it convenient?
Well, as far as I can tell there are four components involved in making it work:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The ability to write &lt;code&gt;&#x27;self&lt;&#x2F;code&gt; lifetimes.&lt;&#x2F;li&gt;
&lt;li&gt;The ability to construct types from functions in fixed memory locations.&lt;&#x2F;li&gt;
&lt;li&gt;A way to mark types as &quot;immovable&quot; in the type system.&lt;&#x2F;li&gt;
&lt;li&gt;The ability to safely initialize self-references in structs without going through an option-dance.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;It&#x27;s only once we have all four of these components that writing
self-referential types can become accessible to most regular Rust programmers.
And that seems important, because as we&#x27;ve seen with &lt;code&gt;async {}&lt;&#x2F;code&gt; and &lt;code&gt;Future&lt;&#x2F;code&gt;:
once you start writing sufficiently complex state machines, being able to track
references into data becomes incredibly useful.&lt;&#x2F;p&gt;
&lt;p&gt;Speaking of &lt;code&gt;async&lt;&#x2F;code&gt; and &lt;code&gt;Future&lt;&#x2F;code&gt;: in this post we&#x27;ll be using that as a
motivating example for how these features can work together. Because if it seems
realistic that we can make that a case as complex as that work, other simpler
cases should probably work too.&lt;&#x2F;p&gt;
&lt;p&gt;Oh and before we dive in, I want to give a massive shout-out to Eric Holk. We&#x27;ve
spent several hours working through the type-system implications of &lt;code&gt;!Move&lt;&#x2F;code&gt;
together, and worked through a number of edge cases and issues. I can&#x27;t be
solely credited for the ideas in this post. However any  mistakes in this post are mine, and I’m not claiming to speak for the both of us.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Disclaimer: This post is not a fully-formed design. It is an early exploration
of how several features could work together to solve a broader problem. My goal
is primarily to narrow down the design space to a tangible list of features
which can be progressively implemented, and share it with the broader Rust
community for feedback. I&#x27;m not on the lang team, nor do I speak for the lang
team.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;motivating-example&quot;&gt;Motivating example&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s take &lt;code&gt;async {}&lt;&#x2F;code&gt; and &lt;code&gt;Future&lt;&#x2F;code&gt; as our examples here. When we borrow local
variables in an &lt;code&gt;async {}&lt;&#x2F;code&gt; block across &lt;code&gt;.await&lt;&#x2F;code&gt; points, the resulting state
machine will store both the concrete value and a reference to that value in the
same state machine struct. That state machine is what we call
&lt;em&gt;self-referential&lt;&#x2F;em&gt;, because it has a &lt;em&gt;reference&lt;&#x2F;em&gt; which points to something in
&lt;em&gt;self&lt;&#x2F;em&gt;. And because references are pointers to concrete memory addresses, there
are challenges around ensuring they are never invalidated as that would result
in undefined behavior. Let&#x27;s look at an example async function:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;give_pats&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; data = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;chashu tuna&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;();       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Owned value declared
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; name = data.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39; &amp;#39;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Obtain a reference
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;pat_cat&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;name).await;                       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `.await` point here
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;patted &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{name}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);                  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Reference used here
&lt;&#x2F;span&gt;&lt;span&gt;} 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;give_pats&lt;&#x2F;span&gt;&lt;span&gt;().await; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Calls the `give_pats` function.
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a pretty simple program, but the idea should come across well enough: we
declare an owned value in-line, we call an &lt;code&gt;.await&lt;&#x2F;code&gt; function, and later on we
reference the owned value again. This keeps a reference live across an &lt;code&gt;.await&lt;&#x2F;code&gt;
point, and that requires self-referential types. We can desugar this to a future
state machine &lt;a href=&quot;https:&#x2F;&#x2F;tmandry.gitlab.io&#x2F;blog&#x2F;posts&#x2F;optimizing-await-1&#x2F;&quot;&gt;like so&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;GivePatsState {
&lt;&#x2F;span&gt;&lt;span&gt;    Created,       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Marks our future has been created
&lt;&#x2F;span&gt;&lt;span&gt;    Suspend1,      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Marks the first `.await` point
&lt;&#x2F;span&gt;&lt;span&gt;    Complete,      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Marks the future is now done
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;GivePatsFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;resume_from&lt;&#x2F;span&gt;&lt;span&gt;: GivePatsState,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: Option&amp;lt;String&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: Option&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Note the lack of a lifetime here
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;GivePatsFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            resume_from: GivePatsState::Created,
&lt;&#x2F;span&gt;&lt;span&gt;            data: None,
&lt;&#x2F;span&gt;&lt;span&gt;            name: None,
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Future &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;GivePatsFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output = ();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; { ... }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The lifetime of &lt;code&gt;GivePatsFuture::name&lt;&#x2F;code&gt; is unknown, mainly because we can&#x27;t name
it. And because the desugaring happens in the compiler, it doesn&#x27;t have to name
the lifetime either. We&#x27;ll talk more about that later in this post. Because this
generates a self-referential state machine, this future will need to be fixed
in-place using &lt;code&gt;Pin&lt;&#x2F;code&gt; first. Once pinned, the &lt;code&gt;Future::poll&lt;&#x2F;code&gt; method can be called
in a loop until the future yields &lt;code&gt;Ready&lt;&#x2F;code&gt;. The desugaring for that will look
something &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;reference&#x2F;expressions&#x2F;await-expr.html&quot;&gt;like this&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; future = IntoFuture::into_future(GivePatsFuture::new());
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; pinned = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Pin::new_unchecked(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; future) };
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; pinned.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; current_context) {
&lt;&#x2F;span&gt;&lt;span&gt;        Poll::Ready(ready) =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt; ready,
&lt;&#x2F;span&gt;&lt;span&gt;        Poll::Pending =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;yield&lt;&#x2F;span&gt;&lt;span&gt; Poll::Pending,
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And finally, just for reference, here is what the traits we&#x27;re using look like
today. The main bit that&#x27;s interesting here for the purpose of this post is that
&lt;code&gt;Future&lt;&#x2F;code&gt; takes a &lt;code&gt;Pin&amp;lt;&amp;amp;mut Self&amp;gt;&lt;&#x2F;code&gt;, which we&#x27;ll be explaining how it can be
replaced with a simpler system throughout the remainder of this post.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;IntoFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;IntoFuture: Future&amp;lt;Output = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into_future&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;IntoFuture;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Future {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now that we&#x27;ve taken a look at how self-referential futures are desugared  by
the compiler today, let&#x27;s take a look at how we can incrementally replace
it with a safe, user-constructible system.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;self-referential-lifetimes&quot;&gt;Self-referential lifetimes&lt;&#x2F;h2&gt;
&lt;p&gt;In our motivating example we showed the &lt;code&gt;GivePatsFuture&lt;&#x2F;code&gt; which has the &lt;code&gt;name&lt;&#x2F;code&gt;
field that points at the &lt;code&gt;data&lt;&#x2F;code&gt; field. It&#x27;s a clearly a reference, but it does not carry any lifetime:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;GivePatsFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;resume_from&lt;&#x2F;span&gt;&lt;span&gt;: GivePatsState,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: Option&amp;lt;String&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: Option&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Note the lack of a lifetime
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The reason this doesn&#x27;t have a lifetime is not &lt;em&gt;inherent&lt;&#x2F;em&gt;, it&#x27;s because we can&#x27;t
actually name the lifetime here. It&#x27;s not &lt;code&gt;&#x27;static&lt;&#x2F;code&gt; because it isn&#x27;t valid for
the remainder of the program. In the compiler today I believe we can just omit
the lifetime because the codegen happens after the lifetimes have already been
checked. But say we wanted to write this by hand today as-is; we would need a
concept for an &quot;unchecked lifetime&quot;, something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;GivePatsFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;resume_from&lt;&#x2F;span&gt;&lt;span&gt;: GivePatsState,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: Option&amp;lt;String&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: Option&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;unsafe str&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Unchecked lifetime
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Being able to write a lifetime that isn&#x27;t checked by the compiler would be the
first-click stop to enable writing self-referential structs by hand. It would
just require a lot of &lt;code&gt;unsafe&lt;&#x2F;code&gt; and anxiety to get right. But at least it would
be possible. I believe folks on T-compiler are already working on adding this,
which seems like a great idea.&lt;&#x2F;p&gt;
&lt;p&gt;But even better would be if we could describe &lt;em&gt;checked&lt;&#x2F;em&gt; lifetimes here. What we
actually want to write here is a lifetime which is valid for the duration of the
value - and it would always be guaranteed to be valid. Adding this lifetime
would come with additional constraints we&#x27;ll get into later in this post (e.g.
the type wouldn&#x27;t be able to move), but what we really want is to be able to
write something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;GivePatsFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;resume_from&lt;&#x2F;span&gt;&lt;span&gt;: GivePatsState,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: Option&amp;lt;String&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: Option&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;self str&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Valid for the duration of `Self`
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To sidetrack slightly; adding a named &lt;code&gt;&#x27;self&lt;&#x2F;code&gt; lifetime could also allow us to remove the
&lt;code&gt;where Self: &#x27;a&lt;&#x2F;code&gt; boilerplate when using lifetimes in generic associated types. If you&#x27;ve ever
worked with lifetimes in associated types, then you&#x27;ll likely have run into the &quot;missing required bounds&quot; error. Niko suggested in &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;87479#issue-952936723&quot;&gt;this
issue&lt;&#x2F;a&gt; using &lt;code&gt;&#x27;self&lt;&#x2F;code&gt; as one possible solution for the bounds boilerplate. I
think its meaning would be slightly different than when used with
self-references? But I don&#x27;t believe using this would be ambiguous
either. And all in all I think it looks rather neat:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; A lending iterator trait as we have to write it today:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;LendingIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;lt;&amp;#39;_&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; A lending iterator trait if we had `&amp;#39;self`:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;LendingIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;lt;&amp;#39;_&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;constructing-types-in-place&quot;&gt;Constructing types in-place&lt;&#x2F;h2&gt;
&lt;p&gt;In order for &lt;code&gt;&#x27;self&lt;&#x2F;code&gt; to be valid, we have to promise our value won&#x27;t move in
memory. And before we can promise a value won&#x27;t move, we have to first construct
it somewhere we can be sure it can stay and not be moved further. Looking at our
motivating example, the way we achieve this using &lt;code&gt;Pin&lt;&#x2F;code&gt; is a little goofy.
Here&#x27;s that same example again:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;GivePatsFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            resume_from: GivePatsState::Created,
&lt;&#x2F;span&gt;&lt;span&gt;            data: None,
&lt;&#x2F;span&gt;&lt;span&gt;            name: None,
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; future = IntoFuture::into_future(GivePatsFuture::new());
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; pinned = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Pin::new_unchecked(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; future) };
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; pinned.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; current_context) {
&lt;&#x2F;span&gt;&lt;span&gt;            Poll::Ready(ready) =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt; ready,
&lt;&#x2F;span&gt;&lt;span&gt;            Poll::Pending =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;yield&lt;&#x2F;span&gt;&lt;span&gt; Poll::Pending,
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this example we&#x27;re seeing &lt;code&gt;GivePatsFuture&lt;&#x2F;code&gt; being constructed inside of the
&lt;code&gt;new&lt;&#x2F;code&gt; function, be moved out of that, and only then pinned in-place using
&lt;code&gt;Pin::new_unchecked&lt;&#x2F;code&gt;. Even if &lt;code&gt;GivePatsFuture: !Unpin&lt;&#x2F;code&gt;, the &lt;code&gt;Unpin&lt;&#x2F;code&gt; trait only
affects types once they are held inside of a &lt;code&gt;Pin&lt;&#x2F;code&gt; structure. And we can&#x27;t just
return &lt;code&gt;Pin&lt;&#x2F;code&gt; from &lt;code&gt;new&lt;&#x2F;code&gt;, because the function&#x27;s stack frames are discarded the
moment the function returns.&lt;&#x2F;p&gt;
&lt;p&gt;It would be better if we enabled types to describe how they can construct
themselves in-place. That means no more external &lt;code&gt;Pin::new_unchecked&lt;&#x2F;code&gt; calls; but
exclusively internally provided constructors. This enables us to make
self-referential types entirely self-contained, with internally provided
constructors replacing the external pin dance. Here&#x27;s how we could rewrite &lt;code&gt;GivePatsFuture::new&lt;&#x2F;code&gt; to use an internal constructor instead:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;GivePatsFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;slot&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;MaybeUninit&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; slot = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ slot.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get_unchecked_mut&lt;&#x2F;span&gt;&lt;span&gt;() };
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; this: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut Self &lt;&#x2F;span&gt;&lt;span&gt;= slot.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut_ptr&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ 
&lt;&#x2F;span&gt;&lt;span&gt;           addr_of_mut!((*this).resume_from).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(GivePatsState::Created);
&lt;&#x2F;span&gt;&lt;span&gt;           addr_of_mut!((*this).data).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(None);
&lt;&#x2F;span&gt;&lt;span&gt;           addr_of_mut!((*this).name).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(None);
&lt;&#x2F;span&gt;&lt;span&gt;        };
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you don&#x27;t like this: that&#x27;s understandable. I don&#x27;t think anyone does. But
bear with me; we&#x27;re on a little didactic sausage-making journey here together.
I&#x27;m sorry about the sights; let&#x27;s quickly move on.&lt;&#x2F;p&gt;
&lt;p&gt;In &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;in-place-construction-seems-surprisingly-simple&#x2F;&quot;&gt;a recent blog
post&lt;&#x2F;a&gt;
I posited we might be able to think of parameters like these as &quot;spicy return&quot;.
James Munns pointed out that in C++ this feature has a name: out-pointers. And
Jack Huey made an interesting connection between this and the &lt;a href=&quot;https:&#x2F;&#x2F;blog.m-ou.se&#x2F;super-let&#x2F;&quot;&gt;&lt;code&gt;super let&lt;&#x2F;code&gt;
design&lt;&#x2F;a&gt;. Just so we don&#x27;t have to look at a
pile of &lt;code&gt;unsafe&lt;&#x2F;code&gt; code again, let&#x27;s pretend we can combine these into something
coherent:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;GivePatsFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; super Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;super mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        pin!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; just pretend this works
&lt;&#x2F;span&gt;&lt;span&gt;            resume_from: GivePatsState::Created,
&lt;&#x2F;span&gt;&lt;span&gt;            data: None,
&lt;&#x2F;span&gt;&lt;span&gt;            name: None,
&lt;&#x2F;span&gt;&lt;span&gt;        })
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I know, I know - I&#x27;m showing syntax here. I&#x27;m personally &lt;em&gt;meh&lt;&#x2F;em&gt; about the way it
looks and we&#x27;ll talk more later about how we can improve this, but I hope we can
all agree that the function body itself is approximately 400% more legible than the pile of &lt;code&gt;unsafe&lt;&#x2F;code&gt; we
were working with earlier.  We&#x27;ll also get to how we can entirely remove &lt;code&gt;Pin&lt;&#x2F;code&gt;
from the signature, so please don&#x27;t get too hung up on that either.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m asking you to play along here for a second, and pretend we might be able to
do something like this for now, so we can get to the part later on this post
where we can actually fix it. In maybe state this more clearly: this post is
less about proposing concrete designs for a problem, but more about how we can
tease apart the problem of &quot;immovable types&quot; into separate features we can
tackle independently from one another.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;converting-into-immovable-types&quot;&gt;Converting into immovable types&lt;&#x2F;h2&gt;
&lt;p&gt;Alright, so we have an idea of how we might be able to construct immovable types
in-place, provided as a constructor defined on a type. Now while that&#x27;s nice,
we&#x27;ve also lost an important property with that: whenever &lt;code&gt;GivePatsFuture&lt;&#x2F;code&gt; is
constructed, it needs to have a fixed place in memory. Where before we could
freely move it around until we started &lt;code&gt;.await&lt;&#x2F;code&gt;ing it.&lt;&#x2F;p&gt;
&lt;p&gt;One of the main reasons why async is useful is because it &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;why-async-rust&#x2F;&quot;&gt;enables ad-hoc
concurrent execution&lt;&#x2F;a&gt;. That means
we want to be able to take futures and pass them to concurrency operations to
enable concurrency through composition. We can&#x27;t move futures which have a fixed
location in memory, so we need a brief moment where futures can be moved before
they&#x27;re ready to be kept in place and polled to completion.&lt;&#x2F;p&gt;
&lt;p&gt;The way &lt;code&gt;Pin&lt;&#x2F;code&gt; works with this today is that a type can be &lt;code&gt;!Unpin&lt;&#x2F;code&gt; - but that
only becomes relevant once it&#x27;s placed inside of a &lt;code&gt;Pin&lt;&#x2F;code&gt; structure. With futures
that typically doesn&#x27;t happen until it begins being polled, usually via
&lt;code&gt;.await&lt;&#x2F;code&gt;, and so we get the liberty of moving &lt;code&gt;!Unpin&lt;&#x2F;code&gt; futures around until we
start &lt;code&gt;.await&lt;&#x2F;code&gt;ing them. That&#x27;s why &lt;code&gt;!Unpin&lt;&#x2F;code&gt; doesn&#x27;t mark: &quot;A type which cannot
be moved&quot;, it marks: &quot;A type which cannot be moved once it has been pinned&quot;.
This is definitely confusing, so don&#x27;t worry if it&#x27;s hard to follow.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T: Unpin&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;t&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; T);   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Type is not pinned, type can be moved.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;Unpin&amp;gt;(t: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; T);  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Type is not pinned, type can be moved.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T: Unpin&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;t&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; T&amp;gt;);  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Type is pinned, type can be moved.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;Unpin&amp;gt;(t: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; T&amp;gt;); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Type is pinned, type can&amp;#39;t be moved.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we want &quot;immovability&quot; to be unconditionally part of a type, we can&#x27;t
make it behave the same way &lt;code&gt;Unpin&lt;&#x2F;code&gt; does. Instead it seems better to separate
the movable &#x2F; immovable requirements into two separate types. We first construct
a type which can be freely moved around - and once we&#x27;re ready to drive it to
completion, we convert it to a type which is immovable and we begin calling
that. This maps perfectly to the separation between &lt;code&gt;IntoFuture&lt;&#x2F;code&gt; and &lt;code&gt;Future&lt;&#x2F;code&gt; we
already use.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s take a look at our first example again, but modify it slightly. What I&#x27;m
proposing here is that rather than &lt;code&gt;give_pats&lt;&#x2F;code&gt; returning an &lt;code&gt;impl Future&lt;&#x2F;code&gt;, it
should instead return an &lt;code&gt;impl IntoFuture&lt;&#x2F;code&gt;. This type is not pinned, and can be
freely moved around. It&#x27;s only once we&#x27;re ready to &lt;code&gt;.await&lt;&#x2F;code&gt; it that we call
&lt;code&gt;.into_future&lt;&#x2F;code&gt; to obtain the immovable future - and then we call that.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;GivePatsFuture { ... } 
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;GivePatsFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; super Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;super mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; { ... } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; suspend belief pls
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;GivePatsIntoFuture;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;IntoFuture &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;GivePatsIntoFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output = ();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;IntoFuture = GivePatsFuture;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; We call the `Future::new` constructor which gives us a
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `Pin&amp;lt;&amp;amp;&amp;#39;super GivePatsFuture&amp;gt;`, and then rather than writing
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; it into the current function&amp;#39;s stack frame we write it in the
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; caller&amp;#39;s stack frame.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; (keep belief suspended a little longer)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into_future&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; super Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;super mut&lt;&#x2F;span&gt;&lt;span&gt; GivePatsFuture&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        GivePatsFuture::new() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; create in caller&amp;#39;s scope
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Just like we can keep returning values from functions to pass them further up
the call stack, so should we be able to use out-pointers &#x2F; emplacement &#x2F; spicy
allocate in a stack frame further up the call stack. Though even if we didn&#x27;t
support that out of the gate, we could probably in-line the
&lt;code&gt;GivePatsFuture::new&lt;&#x2F;code&gt; into &lt;code&gt;GivePatsIntoFuture::into_future&lt;&#x2F;code&gt; and things would
still work. And with that, our &lt;code&gt;.await&lt;&#x2F;code&gt; desugaring could then look something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; into_future: GivePatsIntoFuture = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;give_pats&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; future: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; GivePats&amp;gt; = GivePatsIntoFuture.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_future&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; future.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; current_context) {
&lt;&#x2F;span&gt;&lt;span&gt;            Poll::Ready(ready) =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt; ready,
&lt;&#x2F;span&gt;&lt;span&gt;            Poll::Pending =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;yield&lt;&#x2F;span&gt;&lt;span&gt; Poll::Pending,
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To re-iterate why this section exists: we can get the same functionality &lt;code&gt;Pin&lt;&#x2F;code&gt; +
&lt;code&gt;Unpin&lt;&#x2F;code&gt; provide today by creating two separate types. One type which can be
freely moved around. And another type which once constructed will not move
locations in memory.&lt;&#x2F;p&gt;
&lt;p&gt;So far the only framing of &quot;immovable types&quot; I&#x27;ve seen so far is a single types
which have both these properties - just like &lt;code&gt;Unpin&lt;&#x2F;code&gt; does today. What I&#x27;m trying
to articulate here is that we can avoid that issue if we choose to create two
types instead, enabling one to construct the other, and make them provide
separate guarantees. I think that&#x27;s a novel insight, and one I thought was important to spend some time on.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;immovable-types&quot;&gt;Immovable types&lt;&#x2F;h2&gt;
&lt;p&gt;Alright, I&#x27;ve been asking folks to suspend belief that we can in fact perform
in-place construction of a &lt;code&gt;Pin&amp;lt;&amp;amp;mut Self&amp;gt;&lt;&#x2F;code&gt; type somehow and that would all work
out the way we want it to. I&#x27;m not sure myself, but for the sake of the
narrative of this post it was easier if we just pretended we could for a second.&lt;&#x2F;p&gt;
&lt;p&gt;The real solution here, of course, to get rid of &lt;code&gt;Pin&lt;&#x2F;code&gt; entirely. Instead types
themselves should be able to communicate whether they have a stable memory
location or not. The simplest formulation for this would be to add a new
built-in auto-trait, &lt;code&gt;Move&lt;&#x2F;code&gt;, which tells the compiler whether a type
can be moved or not.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;auto &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Move {}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is of course not a new idea: we&#x27;ve known about the possibility for &lt;code&gt;Move&lt;&#x2F;code&gt;
since at least 2017. That&#x27;s before I started working on Rust. There were some
staunch advocates for that in the Rust community in favor of &lt;code&gt;Move&lt;&#x2F;code&gt;, but
ultimately &lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rfcs&#x2F;2349-pin.html#comparison-to-move&quot;&gt;that wasn&#x27;t the design we ended up going
with&lt;&#x2F;a&gt;. I
think in hindsight most of will acknowledge that the downsides of &lt;code&gt;Pin&lt;&#x2F;code&gt; are real
enough that revisiting &lt;code&gt;Move&lt;&#x2F;code&gt; and working through its limitations seems like a
good idea &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#blame&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. To explain what the &lt;code&gt;Move&lt;&#x2F;code&gt; trait is: it would be a language-level trait which governs access to the following capabilities:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;blame&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;For anyone looking to assign blame here or pull skeletons out of closets: please don&#x27;t. The higher-order bit here is that we have &lt;code&gt;Pin&lt;&#x2F;code&gt; today, it clearly doesn&#x27;t work as well as was hoped at the time, and we&#x27;d like to replace it with something better. I think the most interesting thing to explore here is how we can move forward and do better.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;ul&gt;
&lt;li&gt;The ability to be passed by-value into functions and types.&lt;&#x2F;li&gt;
&lt;li&gt;The ability to be passed by mutable reference to &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;mem&#x2F;fn.swap.html&quot;&gt;&lt;code&gt;mem::swap&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;mem&#x2F;fn.take.html&quot;&gt;&lt;code&gt;mem::take&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;mem&#x2F;fn.replace.html&quot;&gt;&lt;code&gt;mem::replace&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;The ability to be used with any syntactic equivalents to the earlier points, such
as assigning to mutable references, closure captures, and so on.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Conversely, when a type implements &lt;code&gt;!Move&lt;&#x2F;code&gt; they would not have access to any of
these capabilities - making it so they cannot be moved once they have a fixed
memory location. And by default we would assume in all bounds that types are
&lt;code&gt;Move&lt;&#x2F;code&gt;, except for places that explicitly opt-out by using &lt;code&gt;+ ?Move&lt;&#x2F;code&gt;. Here are
examples of things that constitute moves:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; # examples of moving
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ## swapping two values
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; x = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;new_thing&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; y = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;new_thing&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;swap&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; x, &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; y);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ## passing by value
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;: T) {}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;new_thing&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(x);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ## returning a value
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;make_value&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Foo {
&lt;&#x2F;span&gt;&lt;span&gt;    Foo {
&lt;&#x2F;span&gt;&lt;span&gt;        x: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;42
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ## `move` closure captures
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;new_thing&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;thread::spawn(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;|| {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x = x;
&lt;&#x2F;span&gt;&lt;span&gt;})
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And here are some things that do not constitute moves:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; # things that are not moves
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ## passing a reference
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;take_ref&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;T) {}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;new_thing&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take_ref&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;x);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ## passing mutable references is also okay,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;    but you have to be careful how you use it
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;take_mut_ref&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; T) {}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; x = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;new_thing&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take_mut_ref&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; x);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Passing types by-value will &lt;em&gt;never&lt;&#x2F;em&gt; be compatible with &lt;code&gt;!Move&lt;&#x2F;code&gt; types because that’s what a move is. Passing
types by-reference will &lt;em&gt;always&lt;&#x2F;em&gt; be compatible with &lt;code&gt;!Move&lt;&#x2F;code&gt; types because they are immutable &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#immutable&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. The only place with some ambiguity is when we work with
mutable references, as things like &lt;code&gt;mem::swap&lt;&#x2F;code&gt; allow us to violate the
immovability guarantees.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;immutable&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Yes yes, we&#x27;ll get to internal mutability in a second here.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;If a function wants to take a mutable reference which may be immovable, they
will have to add &lt;code&gt;+ ?Move&lt;&#x2F;code&gt; to it. If a function does not use &lt;code&gt;+ ?Move&lt;&#x2F;code&gt; on their
mutable reference, then a &lt;code&gt;!Move&lt;&#x2F;code&gt; type cannot be passed to it. In practice this
will work as follows:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;meow&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span&gt;: T);            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; by-value,   can&amp;#39;t pass `!Move` values
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;meow&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;T);           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; by-ref,     can pass `!Move` values
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;meow&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; T);       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; by-mut-ref, can&amp;#39;t pass `!Move` values
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;meow&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;Move&amp;gt;(cat: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; T) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; by-mut-ref, can pass `!Move` values
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;By default all &lt;code&gt;cat: &amp;amp;mut T&lt;&#x2F;code&gt; bounds would imply &lt;code&gt;+ Move&lt;&#x2F;code&gt;. And only where we
opt-in to &lt;code&gt;+ ?Move&lt;&#x2F;code&gt; could &lt;code&gt;!Move&lt;&#x2F;code&gt; types be passed. In practice it seems likely
most places will probably be fine adding &lt;code&gt;+ ?Move&lt;&#x2F;code&gt;, since it&#x27;s far more common
to write to a field of a mutable reference than it is to replace it whole-sale
using &lt;code&gt;mem::swap&lt;&#x2F;code&gt;. Things like interior mutability are probably also largely
fine under these rules, since even if accesses go through shared references,
updating the values in the pointers will have to interact with the earlier rules
we&#x27;ve set out - and those are safe by default.&lt;&#x2F;p&gt;
&lt;p&gt;To be entirely accurate we also have to consider internal mutability. That
allows us to mutate values through shared references - but only by being able to
conditionally convert it to &lt;code&gt;&amp;amp;mut&lt;&#x2F;code&gt; references at runtime. Just because we allow
casting &lt;code&gt;&amp;amp;T&lt;&#x2F;code&gt; to &lt;code&gt;&amp;amp;mut T&lt;&#x2F;code&gt; at runtime, doesn&#x27;t mean that the rules we&#x27;ve applied
to the system don&#x27;t still work. Say we held an &lt;code&gt;&amp;amp;mut T: !Move&lt;&#x2F;code&gt; inside of a
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;sync&#x2F;struct.Mutex.html&quot;&gt;Mutex&lt;&#x2F;a&gt;. If we tried to
call the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;sync&#x2F;struct.MutexGuard.html#impl-DerefMut-for-MutexGuard%3C&amp;#x27;_,+T%3E&quot;&gt;&lt;code&gt;deref_mut&lt;&#x2F;code&gt;
method&lt;&#x2F;a&gt;,
we&#x27;d get a compile-error because that bound hasn&#x27;t yet declared that &lt;code&gt;T: ?Move&lt;&#x2F;code&gt;.
We could probably add that, but because it doesn&#x27;t work by default we&#x27;d have an
opportunity to validate its soundness before adding it.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, that&#x27;s enough theory about how this should probably work for now. Let&#x27;s
try and update our earlier example, replacing &lt;code&gt;Pin&lt;&#x2F;code&gt; with &lt;code&gt;!Move&lt;&#x2F;code&gt;. That should be
as simple as adding a &lt;code&gt;!Move&lt;&#x2F;code&gt; impl on &lt;code&gt;GivePatsFuture&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;GivePatsFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;resume_from&lt;&#x2F;span&gt;&lt;span&gt;: GivePatsState,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: Option&amp;lt;String&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: Option&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;self str&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;!Move for GivePatsFuture {}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And once we have that, we can change our constructors to return &lt;code&gt;super Self&lt;&#x2F;code&gt;
instead of &lt;code&gt;super Pin&amp;lt;&amp;amp;&#x27;super mut Self&amp;gt;&lt;&#x2F;code&gt;. We already know that emplacement using
something like &lt;code&gt;super Self&lt;&#x2F;code&gt; (not actual notation) to write to fixed memory
locations seems plausible. All we then need to do is add an auto-trait which tells the type-system that further move operations aren&#x27;t allowed.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;GivePatsFuture { ... } 
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;!Move for GivePatsFuture {}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;GivePatsFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; super &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ ... } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; create in caller&amp;#39;s scope
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;GivePatsIntoFuture;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;IntoFuture &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;GivePatsIntoFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output = ();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;IntoFuture = GivePatsFuture;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into_future&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; super GivePatsFuture {
&lt;&#x2F;span&gt;&lt;span&gt;        GivePatsFuture::new() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; create in caller&amp;#39;s scope
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I probably should have said this sooner, but I&#x27;ll say it now: in this post I&#x27;m
intentionally not bothering with backwards-compat. The point, again, is to break
the complicated design space of &quot;immovable types&quot; into smaller problems we can
tackle one-by-one. Figuring out how to bridge &lt;code&gt;Pin&lt;&#x2F;code&gt; and &lt;code&gt;!Move&lt;&#x2F;code&gt; is something we
will want to figure out at some point - but not now.&lt;&#x2F;p&gt;
&lt;p&gt;As far as &lt;code&gt;async {}&lt;&#x2F;code&gt; and &lt;code&gt;Future&lt;&#x2F;code&gt; are concerned: this should work!
This allows us to freely move around async blocks which desugar into
&lt;code&gt;IntoFuture&lt;&#x2F;code&gt;. And only once we&#x27;re ready to start polling them do we call
&lt;code&gt;into_future&lt;&#x2F;code&gt; to obtain an &lt;code&gt;impl Future + !Move&lt;&#x2F;code&gt;. A system like that is
equivalent to the existing &lt;code&gt;Pin&lt;&#x2F;code&gt; system, but does not need &lt;code&gt;Pin&lt;&#x2F;code&gt; in its
signature. For good measure, here&#x27;s how we would be able to rewrite the
signature of &lt;code&gt;Future&lt;&#x2F;code&gt; with this change:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The current `Future` trait
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; using `Pin&amp;lt;&amp;amp;mut Self&amp;gt;`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Future {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The `Future` trait leveraging `Move`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; using `&amp;amp;mut self`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Future {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That would also mean: no more &lt;code&gt;Pin&lt;&#x2F;code&gt;-projections. No more incompatibilities with
&lt;code&gt;Drop&lt;&#x2F;code&gt;. Because it&#x27;s an auto-trait that governs language behavior, as long as
the base rules are sound, the interaction with all other parts of Rust would be sound.&lt;&#x2F;p&gt;
&lt;p&gt;Also, most relevant for me probably, this would make it possible to write future
state machines using &lt;em&gt;methods&lt;&#x2F;em&gt; and &lt;em&gt;functions&lt;&#x2F;em&gt;, rather than the current status
quo where we just lump everything into the &lt;code&gt;poll&lt;&#x2F;code&gt; function body. After having
written a ridiculous amount of futures by hand over the past six years, I can&#x27;t
tell you how much I&#x27;d love to be able to do that.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;motivating-example-reworked&quot;&gt;Motivating example, reworked&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we&#x27;ve covered self-referential lifetimes, in-place construction,
understand &lt;code&gt;async {}&lt;&#x2F;code&gt; should return &lt;code&gt;IntoFuture&lt;&#x2F;code&gt;, and have seen &lt;code&gt;!Move&lt;&#x2F;code&gt;, we&#x27;re
ready to bring these features together to rework our motivating example. This is
what we started with using regular &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; code:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;give_pats&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; data = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;chashu tuna&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; name = data.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39; &amp;#39;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;pat_cat&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;name).await;
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;patted &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{name}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;} 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;give_pats&lt;&#x2F;span&gt;&lt;span&gt;().await;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And here is what that, with these new capabilities, here is what &lt;code&gt;async fn give_pats&lt;&#x2F;code&gt; would be able to desugar to.  Note the &lt;code&gt;&#x27;self&lt;&#x2F;code&gt; lifetime, the &lt;code&gt;!Move&lt;&#x2F;code&gt;
impl for the future, the omission of &lt;code&gt;Pin&lt;&#x2F;code&gt; everywhere, and the in-place
construction of the type.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;GivePatsState {
&lt;&#x2F;span&gt;&lt;span&gt;    Created,
&lt;&#x2F;span&gt;&lt;span&gt;    Suspend1,
&lt;&#x2F;span&gt;&lt;span&gt;    Complete,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;GivePatsFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;resume_from&lt;&#x2F;span&gt;&lt;span&gt;: GivePatsState,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: Option&amp;lt;String&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: Option&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;self str&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Note the `&amp;#39;self` lifetime
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;!Move for GivePatsFuture {}     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← This type is immovable
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Future &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;GivePatsFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output = ();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;)  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← No `Pin` needed
&lt;&#x2F;span&gt;&lt;span&gt;        -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; { ... }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;IntoGivePatsFuture {}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;IntoFuture &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;IntoGivePatsFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output = ();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;IntoFuture: GivePatsFuture
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into_future&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;        -&amp;gt; super GivePatsFuture {  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Writes to a stable addr
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            resume_from: GivePatsState::Created,
&lt;&#x2F;span&gt;&lt;span&gt;            data: None,
&lt;&#x2F;span&gt;&lt;span&gt;            name: None,
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And finally, we can then desugar the &lt;code&gt;give_pats().await&lt;&#x2F;code&gt; call to concrete types
we construct and call to completion:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; into_future = IntoGivePatsFuture {};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; future = into_future.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_future&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Immovable without `Pin`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; future.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; current_context) {
&lt;&#x2F;span&gt;&lt;span&gt;        Poll::Ready(ready) =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt; ready,
&lt;&#x2F;span&gt;&lt;span&gt;        Poll::Pending =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;yield&lt;&#x2F;span&gt;&lt;span&gt; Poll::Pending,
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And with that, we should have a working example of &lt;code&gt;async {}&lt;&#x2F;code&gt; blocks, desugared
to concrete types and traits that don&#x27;t use &lt;code&gt;Pin&lt;&#x2F;code&gt; anywhere at all. Accessing
fields within it wouldn&#x27;t go through any kind of pin projection, and there would
no longer be any need for things like stack-pinning. Immovability would just be
a property of the types themselves, constructed when we need them in the place
where we want to use them.&lt;&#x2F;p&gt;
&lt;p&gt;Oh and I guess just to mention it: functions working with these traits would
always want to use &lt;code&gt;T: IntoFuture&lt;&#x2F;code&gt; rather than &lt;code&gt;T: Future&lt;&#x2F;code&gt;. That&#x27;s not a big
change, and actually something people should already be doing today. But I
figured I&#x27;d mention it in case people are confused about what the bounds should
be for concurrency operations.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;phased-initialization&quot;&gt;Phased initialization&lt;&#x2F;h2&gt;
&lt;p&gt;We didn&#x27;t show this in our example, but there is one more aspect to
self-referential types worth covering: phased initialization. This is when you
initialize parts of a type at separate points in time. In our motivating example
we didn&#x27;t have to use that, because the self-references lived inside of an
&lt;code&gt;Option&lt;&#x2F;code&gt;. That means that when we initialized the type we could just pass
&lt;code&gt;None&lt;&#x2F;code&gt;, and things were fine. However, say we did want to initialize a
self-reference, how would we go about that?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: String,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;self str&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;!Move for Cat {}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: String) -&amp;gt; super &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        Cat {
&lt;&#x2F;span&gt;&lt;span&gt;            data: &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;chashu tuna&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;            name: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;* How do we reference `self.data` here? *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now of course because &lt;code&gt;String&lt;&#x2F;code&gt; is heap-allocated, its address is actually stable
and so we could write something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: String,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;self str&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;!Move for Cat {}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: String) -&amp;gt; super &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; data = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;chashu tuna&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        Cat {
&lt;&#x2F;span&gt;&lt;span&gt;            name: data.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39; &amp;#39;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;            data, 
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s clearly cheating, and not what we want people to have to do. But it does
point us at how the solution here should probably work: we first need a stable
address to point to. And once we have that address, we can refer to it. We can&#x27;t
do that if we have to build the entire thing in a single go. But what if we
could do it in multiple &lt;em&gt;phases&lt;&#x2F;em&gt;? That&#x27;s what Niko&#x27;s recent post on &lt;a href=&quot;https:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2024&#x2F;06&#x2F;02&#x2F;the-borrow-checker-within&#x2F;#view-types-also-address-phased-initialization&quot;&gt;borrow
checking and view
types&lt;&#x2F;a&gt; went into. That would allow us to change our example to instead be written like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: String,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;self str&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;!Move for Cat {}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: String) -&amp;gt; super &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;super let&lt;&#x2F;span&gt;&lt;span&gt; this = Cat { data: &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;chashu tuna&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;() }; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← partial init
&lt;&#x2F;span&gt;&lt;span&gt;        this.name = this.data.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39; &amp;#39;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← finish init
&lt;&#x2F;span&gt;&lt;span&gt;        this
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We initialize the owned data in &lt;code&gt;Cat&lt;&#x2F;code&gt; first. And once we have that, we can then
initialize the references to it. These references would be &lt;code&gt;&#x27;self&lt;&#x2F;code&gt;, we sprinkle
in a &lt;code&gt;super let&lt;&#x2F;code&gt; annotation to indicate we&#x27;re placing this in the caller&#x27;s
scope, and everything should subsequently check out.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;migrating-from-pin-to-move&quot;&gt;Migrating from Pin to Move&lt;&#x2F;h2&gt;
&lt;p&gt;What we didn&#x27;t cover in this post is any migration story from the existing
&lt;code&gt;Pin&lt;&#x2F;code&gt;-based APIs to the new &lt;code&gt;Move&lt;&#x2F;code&gt;-based system. If we want to move off of &lt;code&gt;Pin&lt;&#x2F;code&gt;
in favor of &lt;code&gt;Move&lt;&#x2F;code&gt;, the only path plausible way I see is by minting new traits
that don&#x27;t carry &lt;code&gt;Pin&lt;&#x2F;code&gt; in its signature, and providing bridging impls from the
old traits to the new traits. A basic conversion with an explicit method could
look like this, though blanket impls could also be a possibility:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;NewFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, ...) { ... }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Future {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, ...) { ... }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Convert this future into a `NewFuture`.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into_new_future&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) -&amp;gt; NewFutureWrapper&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; { ... }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A wrapper bridging the old future trait to the new future trait.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;NewFutureWrapper&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;, F: Future&amp;gt;(Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a mut&lt;&#x2F;span&gt;&lt;span&gt; F&amp;gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;!Move for NewFutureWrapper {}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;, F&amp;gt; NewFuture &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;NewFutureWrapper&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;, F&amp;gt; { ... }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I&#x27;ve been repeating this line for at least three years now: but if we want to
fix the problems with &lt;code&gt;Pin&lt;&#x2F;code&gt;, the first step we need to take is to not make the
problem worse. If the stdlib needs to fix the &lt;code&gt;Future&lt;&#x2F;code&gt; trait once, that sucks
but it&#x27;s fine and we&#x27;ll find a way to do it. But if we tie &lt;code&gt;Pin&lt;&#x2F;code&gt; up into a
number of other traits, the problems will compound and I&#x27;m no longer sure
whether we can rid ourselves of &lt;code&gt;Pin&lt;&#x2F;code&gt;. And that&#x27;s a problem, because &lt;code&gt;Pin&lt;&#x2F;code&gt; is
broadly disliked and we actively want to get rid of it.&lt;&#x2F;p&gt;
&lt;p&gt;Compatibility with self-referential types is not only relevant for iteration;
it&#x27;s a generalized property which ends up interacting with nearly every trait,
function, and language feature. &lt;code&gt;Move&lt;&#x2F;code&gt; just composes with any other trait, and
so there&#x27;s no need for a special &lt;code&gt;PinnedRead&lt;&#x2F;code&gt; or anything. A type would instead
just implement &lt;code&gt;Read + Move&lt;&#x2F;code&gt;, and that would be enough for a self-referential
reader to function. And we can repeat that for any other combination of traits.&lt;&#x2F;p&gt;
&lt;p&gt;In-place construction of course does change the signature of traits. But in
order to support that in a backwards-compatible way, all we&#x27;d need to do is
enable traits to opt-in to &lt;em&gt;&quot;can perform in-place construction&quot;&lt;&#x2F;em&gt;. And being able
to gradually roll-out capabilities like that is exactly why we&#x27;re working on
effect generics.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;IntoFuture {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;IntoFuture: Future&amp;lt;Output = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Marked as compatible with in-place construction, with
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; implementations being able to decide whether they want
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; to use it or not.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into_future&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;maybe&lt;&#x2F;span&gt;&lt;span&gt;(super)] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::IntoFuture;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we want self-referential types to be generally useful, they need to
practically compose with most other features we have. And so really, the first
step to getting there is stop stabilizing any new traits in the stdlib which use
&lt;code&gt;Pin&lt;&#x2F;code&gt; in its signature.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;making-immovable-types-movable&quot;&gt;Making immovable types movable&lt;&#x2F;h2&gt;
&lt;p&gt;So far we’ve been talking a lot about self-referential types and how we need to
make sure they cannot be moved, because moving them would be bad. But what if we
did allow them to be moved? In C++ this is possible using a feature called
&lt;em&gt;&quot;move constructors&quot;&lt;&#x2F;em&gt;, and if we supported self-referential types in Rust, it
doesn&#x27;t seem like a big leap to support that too.&lt;&#x2F;p&gt;
&lt;p&gt;Before we go any further I want to preface this: I&#x27;ve heard from people who have
worked with move constructors in C++ that they can be rather tricky to work
with. I haven&#x27;t worked with them, so I can&#x27;t speak from experience. Personally I
don&#x27;t really have any uses where I feel like I would have wanted move
constructors, so I&#x27;m not particularly in favor or against supporting them. I&#x27;m
writing this section mostly out of academic interest, because I know there will
be people wondering about this. And the rules for how this should work seem
fairly straightforward.&lt;&#x2F;p&gt;
&lt;p&gt;Niko Matsakis recently wrote a two-parter on the &lt;code&gt;Claim&lt;&#x2F;code&gt; trait
(&lt;a href=&quot;https:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2024&#x2F;06&#x2F;21&#x2F;claim-auto-and-otherwise&#x2F;&quot;&gt;first&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2024&#x2F;06&#x2F;26&#x2F;claim-followup-1&#x2F;&quot;&gt;second&lt;&#x2F;a&gt;),
proposing a new &lt;code&gt;Claim&lt;&#x2F;code&gt; trait to fill the gap between &lt;code&gt;Clone&lt;&#x2F;code&gt; and &lt;code&gt;Copy&lt;&#x2F;code&gt;. This
trait would be for types which are &quot;cheap&quot; to clone, such as the &lt;code&gt;Arc&lt;&#x2F;code&gt; and &lt;code&gt;Rc&lt;&#x2F;code&gt;
types. And using
&lt;a href=&quot;https:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2024&#x2F;06&#x2F;21&#x2F;claim-auto-and-otherwise&#x2F;#autoclaim-to-the-rescue&quot;&gt;autoclaim&lt;&#x2F;a&gt;,
the compiler would automatically insert calls to &lt;code&gt;.claim&lt;&#x2F;code&gt; as needed. For example
when a &lt;code&gt;move ||&lt;&#x2F;code&gt; closure captures a type implementing &lt;code&gt;Claim&lt;&#x2F;code&gt; but it is already
in use somewhere else - it would automatically call &lt;code&gt;.claim&lt;&#x2F;code&gt; so it would compile.&lt;&#x2F;p&gt;
&lt;p&gt;Enabling immovable types to relocate would work much the same as auto-claiming
would. We would need to introduce a new trait, which we&#x27;ll call &lt;code&gt;Relocate&lt;&#x2F;code&gt; here,
with a method &lt;code&gt;relocate&lt;&#x2F;code&gt;. Whenever we tried to move an otherwise immovable
value, we would automatically call &lt;code&gt;.relocate&lt;&#x2F;code&gt; instead. The signature of the
&lt;code&gt;Relocate&lt;&#x2F;code&gt; trait would take &lt;code&gt;self&lt;&#x2F;code&gt; as a mutable reference. And return an
instance of &lt;code&gt;Self&lt;&#x2F;code&gt;, constructed in-place:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Relocate {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;relocate&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; super &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note the signature of &lt;code&gt;self&lt;&#x2F;code&gt; here: we take it by mutable reference - not owned
nor shared. That is because what we&#x27;re writing is effectively the immovable
equivalent to &lt;code&gt;Into&lt;&#x2F;code&gt;, but we can&#x27;t take self by-value - so we have to take it
by-reference instead and tell people to just &lt;code&gt;mem::swap&lt;&#x2F;code&gt; away. Applying this our
earlier &lt;code&gt;Cat&lt;&#x2F;code&gt; example, we would be able to implement it as follows:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: String,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;self str&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: String) -&amp;gt; super &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ ... }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Relocate &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;relocate&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; super &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; data = String::new(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; dummy type, does not allocate
&lt;&#x2F;span&gt;&lt;span&gt;        mem::swap(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.data, &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; data); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; take owned data
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;super let&lt;&#x2F;span&gt;&lt;span&gt; cat = Cat { data }; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; construct new instance
&lt;&#x2F;span&gt;&lt;span&gt;        cat.name = cat.data.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39; &amp;#39;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; create self-ref
&lt;&#x2F;span&gt;&lt;span&gt;        cat
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We&#x27;re making one sketchy assumption here: we need to be able to take the owned
data from &lt;code&gt;self&lt;&#x2F;code&gt;, without running into the issue where the data can&#x27;t be moved
because it is already borrowed from &lt;code&gt;self&lt;&#x2F;code&gt;. This is a general problem we need to
solve, and one way we could for example work around this is by creating dummy
pointers in the main struct to ensure the types are always valid - but we
invalidate the types:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: String,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;dummy_data&lt;&#x2F;span&gt;&lt;span&gt;: String, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; never initialized with a value
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;self str&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Relocate &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;relocate&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; super &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.name = &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.dummy_data; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; no more references to `self.data`
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; data = mem::take(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.data); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; shorter than `mem::swap`
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;super let&lt;&#x2F;span&gt;&lt;span&gt; cat = Cat { data };
&lt;&#x2F;span&gt;&lt;span&gt;        cat.name = cat.data.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39; &amp;#39;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        cat
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this example the &lt;code&gt;Cat&lt;&#x2F;code&gt; would implement &lt;code&gt;Move&lt;&#x2F;code&gt; even if it has a &lt;code&gt;&#x27;self&lt;&#x2F;code&gt;
lifetime, because we can freely move around. When a type is dropped after having
been passed to &lt;code&gt;Relocate&lt;&#x2F;code&gt;, it should not call its &lt;code&gt;Drop&lt;&#x2F;code&gt; impl. Because
semantically we&#x27;re not trying to drop the type - all we&#x27;re doing is updating its
location in memory. Under these rules access to &lt;code&gt;&#x27;self&lt;&#x2F;code&gt; in structs would be
available both if &lt;code&gt;Self: !Move&lt;&#x2F;code&gt; OR &lt;code&gt;Self: Relocate&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I want to again emphasize that I&#x27;m not directly advocating here for the
introduction of move constructors to Rust. Personally I&#x27;m pretty neutral about
them, and I can be convinced either way. I mainly wanted to have at least once
walked through the  out the way move constructors could work, because it seems
like a good idea to know a gradual path here should be possible. Hopefully that
point is coming across okay here.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;further-reading&quot;&gt;Further reading&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;code&gt;Pin&lt;&#x2F;code&gt; &lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rfcs&#x2F;2349-pin.html&quot;&gt;RFC&lt;&#x2F;a&gt; is an
interesting read as it describes the system for immovable types we ended up
going with today. Specifically &lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rfcs&#x2F;2349-pin.html#comparison-to-move&quot;&gt;the
comparison&lt;&#x2F;a&gt;
between &lt;code&gt;Pin&lt;&#x2F;code&gt; and &lt;code&gt;Move&lt;&#x2F;code&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rfcs&#x2F;2349-pin.html#drawbacks&quot;&gt;section on
drawbacks&lt;&#x2F;a&gt; are
interesting to read back up on. Especially when we compare it with the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;pin&#x2F;index.html#choosing-pinning-to-be-structural-for-field&quot;&gt;pin
docs&lt;&#x2F;a&gt;,
and see what was not present in the RFC - but later turned out to be major
practical issues (e.g. pin projections, interactions with the rest of the
language).&lt;&#x2F;p&gt;
&lt;p&gt;Tmandry presented an interesting series (&lt;a href=&quot;https:&#x2F;&#x2F;tmandry.gitlab.io&#x2F;blog&#x2F;posts&#x2F;optimizing-await-1&#x2F;&quot;&gt;blog
1&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;tmandry.gitlab.io&#x2F;blog&#x2F;posts&#x2F;optimizing-await-2&#x2F;&quot;&gt;blog
2&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=ZHP9sUqB3Qs&quot;&gt;talk&lt;&#x2F;a&gt;) on async internals.
Specifically he covers how &lt;code&gt;async {}&lt;&#x2F;code&gt; blocks desugar into &lt;code&gt;Future&lt;&#x2F;code&gt;-based state machines.
This post uses that desugaring as its motivating example, so for those keen to
learn more about what happens behind the scenes, this is an excellent resource.
The section on &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;reference&#x2F;expressions&#x2F;await-expr.html&quot;&gt;&lt;code&gt;.await&lt;&#x2F;code&gt;
desugaring&lt;&#x2F;a&gt; in
the Rust reference is also a good read, as it captures the status quo in the
compiler.&lt;&#x2F;p&gt;
&lt;p&gt;More recently Miguel Young de la Sota&#x27;s (mcyoung)
&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=UrDhMWISR3w&quot;&gt;talk&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;moveit&#x2F;latest&#x2F;moveit&#x2F;&quot;&gt;crate&lt;&#x2F;a&gt; to support C++ move constructors
is interesting to read up on. Something I haven&#x27;t fully processed yet, but is
interesting, is the
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;moveit&#x2F;latest&#x2F;moveit&#x2F;new&#x2F;trait.New.html&quot;&gt;&lt;code&gt;New&lt;&#x2F;code&gt; trait&lt;&#x2F;a&gt; it
exposes. This can be used to construct types in-place on both the stack &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;moveit&#x2F;latest&#x2F;moveit&#x2F;new&#x2F;trait.Emplace.html#impl-Emplace%3CT%3E-for-Box%3CT%3E&quot;&gt;and
the heap&lt;&#x2F;a&gt;,
which ideally something like the &lt;code&gt;super let&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;super Type&lt;&#x2F;code&gt; notation could support
too. You can think of C++&#x27;s move constructors as further evolution of immovable
types, so it&#x27;s no surprise that there are lots of shared concepts.&lt;&#x2F;p&gt;
&lt;p&gt;Two years ago I tried formulating a way we could leverage view types for safe
pin projection
(&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;safe-pin-projections-through-view-types&#x2F;#view-types-for-pin-projection&quot;&gt;post&lt;&#x2F;a&gt;),
and I came up short in a few regards. In particular I wasn&#x27;t sure how to deal
with the interactions with &lt;code&gt;#[repr(packed)]&lt;&#x2F;code&gt;, how to make &lt;code&gt;Drop&lt;&#x2F;code&gt; compatible, and
how to mark &lt;code&gt;Unpin&lt;&#x2F;code&gt; as &lt;code&gt;unsafe&lt;&#x2F;code&gt;. There might be a path for the latter, but I&#x27;m
not aware of any practical solutions for the first two issues. This post is
basically a sequel to that post, but changing the premise from: &quot;How can we fix
&lt;code&gt;Pin&lt;&#x2F;code&gt;?&quot; to &quot;How can we replace &lt;code&gt;Pin&lt;&#x2F;code&gt;?&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Niko&#x27;s series on view types is also well worth reading. &lt;a href=&quot;https:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2021&#x2F;11&#x2F;05&#x2F;view-types&#x2F;&quot;&gt;His first
post&lt;&#x2F;a&gt;
discusses what view types are, how they&#x27;d work, and why they&#x27;re useful. And in one of
&lt;a href=&quot;https:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2024&#x2F;06&#x2F;02&#x2F;the-borrow-checker-within&#x2F;&quot;&gt;his most recent
posts&lt;&#x2F;a&gt;
he discusses how view types fall into a broader &quot;4-part roadmap for the borrow
checker&quot; (aka: &quot;the borrow checker within&quot;). In his last post he directly covers
phased initialization using view types as well, which is one of the features we
discuss in this post in relation to self-referential types.&lt;&#x2F;p&gt;
&lt;p&gt;Finally I&#x27;d suggest looking at the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;ouroboros&#x2F;0.18.4&#x2F;ouroboros&#x2F;attr.self_referencing.html&quot;&gt;ouroboros
crate&lt;&#x2F;a&gt;.
It enables safe, phased initialization for self-referential types on stable Rust
by leveraging macros and closures. The way it works is that fields using owned
data are initialized first. And then the closures are executed to initialize
fields referencing the data. Phased initialization using view types as described
in this post emulates that approach, but enables it directly from the language
through a generally useful feature.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve deconstructed &quot;self-referential types&quot; into four constituent parts:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;&#x27;unsafe&lt;&#x2F;code&gt; (unchecked) and &lt;code&gt;&#x27;self&lt;&#x2F;code&gt; (checked) lifetimes which will make it
possible to express self-referential lifetimes.&lt;&#x2F;li&gt;
&lt;li&gt;A moral equivalent to &lt;code&gt;super let&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;-&amp;gt; super Type&lt;&#x2F;code&gt; to safely support
out-pointers.&lt;&#x2F;li&gt;
&lt;li&gt;A way to backwards-compatibly add optional &lt;code&gt;-&amp;gt; super Type&lt;&#x2F;code&gt; notations.&lt;&#x2F;li&gt;
&lt;li&gt;A new &lt;code&gt;Move&lt;&#x2F;code&gt; auto-trait which governs access to move operations.&lt;&#x2F;li&gt;
&lt;li&gt;A view types feature which will make it possible to construct
self-referential types without going through an &lt;code&gt;Option&lt;&#x2F;code&gt; dance.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The final insight this post provides is that today&#x27;s &lt;code&gt;Pin&lt;&#x2F;code&gt; + &lt;code&gt;Unpin&lt;&#x2F;code&gt; system can
be emulated with &lt;code&gt;Move&lt;&#x2F;code&gt; by creating &lt;code&gt;Move&lt;&#x2F;code&gt; wrappers which can return &lt;code&gt;!Move&lt;&#x2F;code&gt;
types. In the context of async, the pattern would be to construct an &lt;code&gt;impl IntoFuture + Move&lt;&#x2F;code&gt; wrapper, which constructs an &lt;code&gt;impl Future + !Move&lt;&#x2F;code&gt; future in-place via an out-pointer.&lt;&#x2F;p&gt;
&lt;p&gt;People generally dislike &lt;code&gt;Pin&lt;&#x2F;code&gt;, and as far as I can tell there is broad support
for exploring alternative solutions such as &lt;code&gt;Move&lt;&#x2F;code&gt;. Right now the only trait
that uses &lt;code&gt;Pin&lt;&#x2F;code&gt; in the stdlib is &lt;code&gt;Future&lt;&#x2F;code&gt;. In order to facilitate a migration
off of &lt;code&gt;Pin&lt;&#x2F;code&gt; to something like &lt;code&gt;Move&lt;&#x2F;code&gt;, we would do well not to further introduce
any &lt;code&gt;Pin&lt;&#x2F;code&gt;-based APIs to the stdlib. Migrating off of a single API will take
effort, but seems ultimately doable. Migrating off of a host of APIs will take
more effort, and makes it more likely we&#x27;ll forever be plagued with the
difficulties of &lt;code&gt;Pin&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The purpose of this post has been to untangle the big scary problem of
&quot;immovable types&quot; into its constituents parts so we can begin tackling them
one-by-one. None of the syntax or semantics in this post are meant to be
concrete or final. I mainly wanted to have at least once walked through
everything required to make immovable types work - so that others can dig in,
think along, and we can begin refining concrete details.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>in-place construction seems surprisingly simple?</title>
            <pubDate>Sat, 22 Jun 2024 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/in-place-construction-seems-surprisingly-simple/</link>
            <guid>https://blog.yoshuawuyts.com/in-place-construction-seems-surprisingly-simple/</guid>
            <description>&lt;h2 id=&quot;introduction&quot;&gt;introduction&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;ve been thinking a little bit about self-referential types recently, and one
of its requirements is that a type, when constructed, has a fixed location in
memory &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#offset-schemes&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. That&#x27;s needed, because a reference is pointer to a
memory address - and if the memory address it points to changes, that would
invalidate the pointer, which can lead to undefined behavior.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;offset-schemes&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Eric Holk and I toyed around for a little while with the idea
of offset-schemes, where we only track offsets from the start of structs. But
that gets weird once you involve non-linear memory such as when using references
in the heap. Using real, actual addresses is probably the better solution since
that should work in all cases - even if it brings its own sets of challenges.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Where this becomes tricky is that returning data from a function constitutes a
&lt;em&gt;move&lt;&#x2F;em&gt;. A constructor which creates a type within itself and returns it, will
change the address of the type it constructs. Take this program which constructs
a type &lt;code&gt;Cat&lt;&#x2F;code&gt; and in the function &lt;code&gt;Cat::new&lt;&#x2F;code&gt; (&lt;a href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=stable&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=dca794dbc7f16686e027a0510cd1e62b&quot;&gt;playground&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::ptr::addr_of;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; this = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ age };
&lt;&#x2F;span&gt;&lt;span&gt;        dbg!(addr_of!(this)); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← first call to `addr_of!`
&lt;&#x2F;span&gt;&lt;span&gt;        this
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cat = Cat::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    dbg!(addr_of!(cat));      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← second call to `addr_of!`
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we run this program we get the following output:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;[src&#x2F;main.rs:7:9] addr_of!(this) = 0x00007ffe0b3575d7 # first call
&lt;&#x2F;span&gt;&lt;span&gt;[src&#x2F;main.rs:14:5] addr_of!(cat) = 0x00007ffe0b357747 # second call
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This shows that the address of &lt;code&gt;Cat&lt;&#x2F;code&gt; &lt;em&gt;within&lt;&#x2F;em&gt; &lt;code&gt;Cat::new&lt;&#x2F;code&gt; is different from the
address once it has been returned from the function. Returning types from
functions means changing addresses. Languages like C++ have ways to work around
this by providing something called &lt;em&gt;move constructors&lt;&#x2F;em&gt;, enable types to update
their own internal addresses when they are moved in memory. But instead, what if
we could just construct types in-place so they didn&#x27;t have to move in the first
place?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;in-place-construction&quot;&gt;in-place construction&lt;&#x2F;h2&gt;
&lt;p&gt;We already perform in-place construction when desugaring &lt;code&gt;async {}&lt;&#x2F;code&gt; blocks, so
this is something we know how to do. And in the ecosystem there is also the
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;moveit&#x2F;latest&#x2F;moveit&#x2F;&quot;&gt;moveit&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;ouroboros&quot;&gt;ouroboros&lt;&#x2F;a&gt; crates. These are all great, but they all
do additional things like &quot;self-references&quot; or &quot;move constructors&quot;. Constructing in-place rather than returning from a function can be useful just for the sake of reducing copies - so let&#x27;s roll our own version of just that.&lt;&#x2F;p&gt;
&lt;p&gt;The way we can do this is by creating a stable location in memory we can store
our value in. Rather than returning a value, a constructor should take a mutable
reference to this memory location and write directly into it instead. And
because we&#x27;re starting with a &lt;em&gt;location&lt;&#x2F;em&gt; and write into it later, this location
needs to be &lt;code&gt;MaybeUninit&lt;&#x2F;code&gt;. If we put those pieces together, we can adapt our
earlier example to the following (&lt;a href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=stable&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=5dddb82fce7229b7b25102c07b809b4f&quot;&gt;playground&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::ptr::{addr_of, addr_of_mut};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::mem::MaybeUninit;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;slot&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;MaybeUninit&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; this: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut Self &lt;&#x2F;span&gt;&lt;span&gt;= slot.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut_ptr&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ 
&lt;&#x2F;span&gt;&lt;span&gt;           addr_of_mut!((*this).age).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(age);
&lt;&#x2F;span&gt;&lt;span&gt;           dbg!(addr_of!(*this));   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← second call to `addr_of!`
&lt;&#x2F;span&gt;&lt;span&gt;        };
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; slot = MaybeUninit::uninit();
&lt;&#x2F;span&gt;&lt;span&gt;    dbg!(addr_of!(slot));      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← first call to `addr_of!`
&lt;&#x2F;span&gt;&lt;span&gt;    Cat::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;, &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; slot);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cat: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; Cat = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ (slot).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;assume_init_mut&lt;&#x2F;span&gt;&lt;span&gt;() };
&lt;&#x2F;span&gt;&lt;span&gt;    dbg!(addr_of!(*cat));      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← third call to `addr_of!`
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we run the program it will print the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;[src&#x2F;main.rs:15:5] addr_of!(slot) = 0x00007ffc9daa590f  # first call
&lt;&#x2F;span&gt;&lt;span&gt;[src&#x2F;main.rs:9:9] addr_of!(*this) = 0x00007ffc9daa590f  # second call
&lt;&#x2F;span&gt;&lt;span&gt;[src&#x2F;main.rs:18:5] addr_of!(*cat) = 0x00007ffc9daa590f  # third call
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To folks who aren&#x27;t used to writing unsafe Rust this might look a little
overwhelming. But what we&#x27;ve done is a fairly mechanical translation. Rather
than returning the type &lt;code&gt;Self&lt;&#x2F;code&gt;, we&#x27;re created a &lt;code&gt;MaybeUninit&amp;lt;Self&amp;gt;&lt;&#x2F;code&gt; and passed
it by-reference. The constructor then writes into it, initializing the memory.
From that point onward, all references to &lt;code&gt;Cat&lt;&#x2F;code&gt; are valid and can be assumed to
be initialized.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately calling &lt;code&gt;assume_init&lt;&#x2F;code&gt; on the actual &lt;em&gt;value&lt;&#x2F;em&gt; of &lt;code&gt;Cat&lt;&#x2F;code&gt; is not
possible because the compiler treats that as a move - which makes sense since it
takes a type and returns another. But that&#x27;s mostly a limitation of how we&#x27;re
doing things - not what we&#x27;re doing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;indirect-in-place-construction&quot;&gt;indirect in-place construction&lt;&#x2F;h2&gt;
&lt;p&gt;Now what happens if there is a degree of indirection? What if rather than
construct just a &lt;code&gt;Cat&lt;&#x2F;code&gt;, we want to construct a &lt;code&gt;Cat&lt;&#x2F;code&gt; inside of a &lt;code&gt;Bed&lt;&#x2F;code&gt;. We would
have to take the memory location of the outer type, and use that as the location
for the inner type. Let&#x27;s extend our first example by doing exactly that (&lt;a href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=stable&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=5fd62e6f92d8e48a391ed1a0fad8648a&quot;&gt;playground&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::ptr::addr_of;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Bed { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span&gt;: Cat }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Bed {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cat = Cat::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ cat }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; this = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ age };
&lt;&#x2F;span&gt;&lt;span&gt;        dbg!(addr_of!(this)); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← first call to `addr_of!`
&lt;&#x2F;span&gt;&lt;span&gt;        this
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; bed = Bed::new();
&lt;&#x2F;span&gt;&lt;span&gt;    dbg!(addr_of!(bed));      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← second call to `addr_of!`
&lt;&#x2F;span&gt;&lt;span&gt;    dbg!(addr_of!(bed.cat));  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← third call to `addr_of!`
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we run the program it will print the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;[src&#x2F;main.rs:15:9] addr_of!(this) = 0x00007fff3910702f
&lt;&#x2F;span&gt;&lt;span&gt;[src&#x2F;main.rs:22:5] addr_of!(bed) = 0x00007fff391071b7
&lt;&#x2F;span&gt;&lt;span&gt;[src&#x2F;main.rs:23:5] addr_of!(bed.cat) = 0x00007fff391071b7
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Adapting our return-based example to preserve referential stability is once
again very mechanical. Rather than returning &lt;code&gt;Self&lt;&#x2F;code&gt; from a function, we pass
a mutable reference to &lt;code&gt;MaybeUninit&amp;lt;Self&amp;gt;&lt;&#x2F;code&gt;. In for &lt;code&gt;Cat&lt;&#x2F;code&gt; to be constructed in
&lt;code&gt;Bed&lt;&#x2F;code&gt;, all we have to do is make sure &lt;code&gt;Bed&lt;&#x2F;code&gt; contains a slot for &lt;code&gt;Cat&lt;&#x2F;code&gt; to be
written to. Put together we end up with the following (&lt;a href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=stable&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=70469053f1c7ea716c6858f55f56b4cb&quot;&gt;playground&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::ptr::{addr_of, addr_of_mut};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::mem::MaybeUninit;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Bed { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span&gt;: MaybeUninit&amp;lt;Cat&amp;gt; }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Bed {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;slot&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;MaybeUninit&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; this: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut Self &lt;&#x2F;span&gt;&lt;span&gt;= slot.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut_ptr&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        Cat::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;(*this).cat });
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;slot&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;MaybeUninit&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; this: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut Self &lt;&#x2F;span&gt;&lt;span&gt;= slot.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut_ptr&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ 
&lt;&#x2F;span&gt;&lt;span&gt;            addr_of_mut!((*this).age).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(age);
&lt;&#x2F;span&gt;&lt;span&gt;            dbg!(addr_of!(*this)); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← second call to `addr_of!`
&lt;&#x2F;span&gt;&lt;span&gt;        };
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; slot = MaybeUninit::uninit();
&lt;&#x2F;span&gt;&lt;span&gt;    dbg!(addr_of!(slot));      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← first call to `addr_of!`
&lt;&#x2F;span&gt;&lt;span&gt;    Bed::new(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; slot);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; bed: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; Bed = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ (slot).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;assume_init_mut&lt;&#x2F;span&gt;&lt;span&gt;() };
&lt;&#x2F;span&gt;&lt;span&gt;    dbg!(addr_of!(*bed));      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← third call to `addr_of!`
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which if we run the program will print the following addresses. These are all
the same because &lt;code&gt;Cat&lt;&#x2F;code&gt; is the only field inside of &lt;code&gt;Bed&lt;&#x2F;code&gt;, so they happen to
point to the same memory location:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;[src&#x2F;main.rs:23:5] addr_of!(slot) = 0x00007fff8271d86f   # first call
&lt;&#x2F;span&gt;&lt;span&gt;[src&#x2F;main.rs:17:9] addr_of!(*this) = 0x00007fff8271d86f  # second call
&lt;&#x2F;span&gt;&lt;span&gt;[src&#x2F;main.rs:26:5] addr_of!(*bed) = 0x00007fff8271d86f   # third call
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;future-possibilities&quot;&gt;future possibilities&lt;&#x2F;h2&gt;
&lt;p&gt;If we squint here it&#x27;s not hard to see how this could be converted into a
language feature. In this post we&#x27;ve mechanically performed a transformation by
hand. Rather than returning a type &lt;code&gt;T&lt;&#x2F;code&gt; from a function, we&#x27;re taking a &lt;code&gt;&amp;amp;mut MaybeUninit&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; and writing into that. It feels like it&#x27;s basically just a
&lt;em&gt;spicy return&lt;&#x2F;em&gt;; and it seems like something we could introduce some kind of
notation for.&lt;&#x2F;p&gt;
&lt;p&gt;Though admittedly things get trickier once we want to also enable self-references,
perform phased initialization, immovable types, and so on. But those all depend
on being able to write to a fixed place in memory - and it feels like perhaps
these are concepts which we can decouple from one another? Anyway, if we just
take in-place construction as a feature, I think we might be able to get away
with something like this for our first example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::ptr::addr_of;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;in_place&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← new notation
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ age }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cat = Cat::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ^ cat was constructed in-place
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is obviously not a new idea - but it stood out to me how simple the actual
underpinnings of in-place construction seem. The change from a regular return to
an in-place return feels mechanical in nature - and that seems like a good sign. For good measure let&#x27;s also adapt our second example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::ptr::addr_of;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Bed { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span&gt;: Cat }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Bed {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;in_place&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← new notation
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ cat: Cat::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;) }
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;     ^ cat was constructed in-place
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;in_place&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← new notation
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ age }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; bed = Bed::new();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ^ bed was constructed in-place
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Admittedly I haven&#x27;t read up on the 10-year discourse of
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;27779&quot;&gt;placement-new&lt;&#x2F;a&gt;, so I assume
there are plenty of details left out that make this hard in the general sense.
Things like heap-addresses and intermediate references. But for the simplest
case? It seems surprisingly doable. Not quite something which we can
proc-macro - but not far off either. And maybe scoping that as a first target
would be enough? I don&#x27;t know.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-connection-to-super-let&quot;&gt;The connection to super let&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;edit 2024-06-25&lt;&#x2F;strong&gt;: This section was added after first publishing this post.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Jack Huey reached out after publishing this post, and
mentioned there might be a connection with &lt;a href=&quot;https:&#x2F;&#x2F;blog.m-ou.se&#x2F;super-let&#x2F;&quot;&gt;the &lt;code&gt;super let&lt;&#x2F;code&gt;
feature&lt;&#x2F;a&gt;. I think that&#x27;s a super interesting
point, and it&#x27;s not hard to see why! Take this example from Mara&#x27;s post:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; writer = {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;opening file...&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; filename = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;super let&lt;&#x2F;span&gt;&lt;span&gt; file = File::create(filename).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    Writer::new(&amp;amp;file)
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;super let file&lt;&#x2F;code&gt; notation here allows the &lt;code&gt;file&lt;&#x2F;code&gt;&#x27;s lifetime to be scoped to
the outer scope, making it valid for &lt;code&gt;Writer&lt;&#x2F;code&gt; to take a reference to &lt;code&gt;file&lt;&#x2F;code&gt; and
return. Without &lt;code&gt;super let&lt;&#x2F;code&gt; this would result in a lifetime error. Its vibes are
very similar to the &lt;code&gt;#[in_place]&lt;&#x2F;code&gt; notation we posited in this post.&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps there a synthesis of both features could exist to create a form of
&quot;generalized super scope&quot; feature? There definitely appears like there might be
some kind of connection. Like, we could imagine writing something like &lt;code&gt;super let&lt;&#x2F;code&gt; to denote a &lt;em&gt;&quot;value which is allocated in the caller&#x27;s frame&quot;&lt;&#x2F;em&gt;. And a
function returning &lt;code&gt;super Type&lt;&#x2F;code&gt; to signal from the type signature that this is
actually an out-pointer &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#outptr&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;outptr&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Shout out to James Munns for teaching me about the term &quot;outpointer&quot; - that&#x27;s apparently the term C++ uses for this using the &lt;code&gt;outptr&lt;&#x2F;code&gt; keyword.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::ptr::addr_of;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; super &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;super let&lt;&#x2F;span&gt;&lt;span&gt; this = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ age };  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; declare in the caller&amp;#39;s frame
&lt;&#x2F;span&gt;&lt;span&gt;        dbg!(addr_of!(this));
&lt;&#x2F;span&gt;&lt;span&gt;        this
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s worth nothing though that this is not an endorsement for actually going
with &lt;code&gt;super let&lt;&#x2F;code&gt; or &lt;code&gt;super Type&lt;&#x2F;code&gt; - but merely to speculate how there might be a
possible connection between both features. I think it&#x27;s fun, and the connection
between both seems worthy of further exploration!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post I&#x27;ve shown how we can construct types in-place using &lt;code&gt;MaybeUninit&lt;&#x2F;code&gt;
which surprised me how simple it ended up being. I mostly wanted to have gone
through the motions at least once - and now I have, and that was fun!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;edit 2024-06-22:&lt;&#x2F;strong&gt; Thanks to Jordan Rose and Simon Sapin for helping un-break
the unsafe pointer code in an earlier version of this post. Goes to show:
Rust&#x27;s pointer ergonomics &lt;a href=&quot;https:&#x2F;&#x2F;faultlore.com&#x2F;blah&#x2F;fix-rust-pointers&#x2F;#fixing-places-and-offsets&quot;&gt;really could use an
overhaul&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Context Managers: Undroppable Types for Free</title>
            <pubDate>Wed, 05 Jun 2024 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/achieving-undroppable-types-by-leveraging-context-managers/</link>
            <guid>https://blog.yoshuawuyts.com/achieving-undroppable-types-by-leveraging-context-managers/</guid>
            <description>&lt;p&gt;In program language design I&#x27;m a big fan of features which fall out of other,
more general features. People occasionally talk about both &quot;unleakable&quot; and
&quot;undroppable&quot; types. I see a lot of value in &quot;unleakable&quot; types because if a
type is &quot;unleakable&quot; we can guarantee the type will always have its destructor
called. This would allow us to use &lt;code&gt;Drop&lt;&#x2F;code&gt; to be used to uphold safety
invariants, which will make it possible to write things like &quot;task scopes&quot;. For
type system nerds: yes, this means Rust would be able to uphold linear
invariants via its type system, AKA equip Rust with linear types.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Undroppable types&quot; have a more limited application. There is some element of
undroppability needed to ensure async destructors can only be called in
async contexts, but that&#x27;s not the same things as a generalized system for
&quot;undroppable types&quot;. The main use for undroppable types is to be able to
&lt;em&gt;guarantee&lt;&#x2F;em&gt; that some type, when destructed, always either takes or returns some
kind of value.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;immovable&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;&lt;&#x2F;div&gt;
&lt;p&gt;I believe it should be possible to express &quot;undroppable types&quot; using Tmandry&#x27;s
design for
&lt;a href=&quot;https:&#x2F;&#x2F;tmandry.gitlab.io&#x2F;blog&#x2F;posts&#x2F;2021-12-21-context-capabilities&#x2F;&quot;&gt;context&#x2F;capabilities&lt;&#x2F;a&gt;.
This design introduces a system similar to Python&#x27;s &quot;context manager&quot; API.
That systems enables additional arguments to be passed to specific trait impls
(like we do with thread-locals today, but via function signatures), which must
be in-scope when the trait is invoked. Assuming the implementation is general
enough, that would enable us to require &lt;code&gt;Drop&lt;&#x2F;code&gt; impls to take extra arguments like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Tuna {}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static str &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Drop &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) with Tuna { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Requires `Tuna` to be in scope when invoked
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt; is snacking on tuna&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.name);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cat = Cat { name: &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Chashu&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; };
&lt;&#x2F;span&gt;&lt;span&gt;    with Tuna {} {  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Bring `Tuna` into the `with`-scope here
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;(cat);  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Prints: &amp;quot;Chashu is snacking on tuna&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That should work pretty well for types which want to require specific arguments
when dropped. Because if &lt;code&gt;Tuna&lt;&#x2F;code&gt; would not be in scope, the type &lt;code&gt;Cat&lt;&#x2F;code&gt;  could not
be dropped. Now where this falls short is if we want to require destructors to
return values too. This is not a MAY return values type of deal, but a MUST
return values. If returning a value was not a hard requirement, then we could
just add some method and use &lt;code&gt;Drop&lt;&#x2F;code&gt; for all other case. But for true
&quot;undroppable types&quot;, it must be impossible for a type to be dropped. That means:
the only way to destruct the value should be by calling the method on it. It
should be possible to express this by leveraging private constructors and
contexts like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Priv { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;_priv&lt;&#x2F;span&gt;&lt;span&gt;: () } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Type can only be constructed in this module
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Loaf { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;_priv&lt;&#x2F;span&gt;&lt;span&gt;: () } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Type can only be constructed in this module
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static str &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Consume `Cat` and returns a sleepy little loaf
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;nap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Loaf {
&lt;&#x2F;span&gt;&lt;span&gt;        with Priv { _priv: () } { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Create a context to drop `Cat`
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;);           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Drop the `Cat` instance
&lt;&#x2F;span&gt;&lt;span&gt;            Loaf { _priv: () }    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← Return some type
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The type `Priv` cannot be externally constructed, meaning this
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; `Drop` impl prevents the type from being dropped outside of the
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; `Cat::nap` method.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Drop &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) with Priv {}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cat = Cat { name: &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Chashu&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; };
&lt;&#x2F;span&gt;&lt;span&gt;    cat.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;nap&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ✅ Compiles as expected.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cat = Cat { name: &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Nori&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; };
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;(cat); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 💥 Compiler: Cannot invoke `impl Drop for Cat`, `Priv` is not in scope.
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I think this is pretty fun: a more general feature with wide applicability could
be leveraged to solve a more niche feature with more limited applications. I bet
if custom diagnostics are generalized enough, we could even improve the error
message here, pointing people to call &lt;code&gt;Cat::nap&lt;&#x2F;code&gt; when they can&#x27;t just drop the
type.&lt;&#x2F;p&gt;
&lt;p&gt;Of course there are a number of other practical applications that come with
undroppable types. The main one being the fact that both any function may
panic, and panic currently equates recoverable control flow. For anyone to even
attempt using undroppable types outside of a demo scenario, they&#x27;d have to
grapple with that. But luckily: that again is something that can be resolved
independently from this. I&#x27;m happy to be able to show that &quot;undroppable
types&quot; does not need to be its own, standalone feature, but instead can be expressed using a more general system &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#undroppable-unleakable&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;undroppable-unleakable&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;For anyone wondering to themselves: &lt;em&gt;&quot;If undroppable
types are more restrictive than unleakable types, can&#x27;t we just use undroppable
types everywhere instead?&quot;&lt;&#x2F;em&gt; - The answer is, &lt;em&gt;&quot;Not practically, no&quot;&lt;&#x2F;em&gt;. Unleakable
types add minor restrictions to the language (e.g. no &lt;code&gt;mem::forget&lt;&#x2F;code&gt;, no &lt;code&gt;Arc&lt;&#x2F;code&gt;,
etc.). Undroppable types add additional major restrictions (e.g. no closure
captures, no holding values across &lt;code&gt;?&lt;&#x2F;code&gt;). Some limitations are acceptable, too
many limitations make the experience painful. For more on this, read my 2023
post: &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;linearity-and-control&#x2F;&quot;&gt;Linearity and
Control&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</description>
        </item>
        <item>
            <title>Tasks are the wrong abstraction</title>
            <pubDate>Sat, 27 Apr 2024 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/tasks-are-the-wrong-abstraction/</link>
            <guid>https://blog.yoshuawuyts.com/tasks-are-the-wrong-abstraction/</guid>
            <description>&lt;p&gt;Okay, so you&#x27;ve probably read the title and are thinking: &lt;em&gt;&quot;Hey is this
clickbait?&quot;&lt;&#x2F;em&gt; - and no dear reader, it is not. I&#x27;m fairly convinced at this point
that tasks, as an abstraction, are not right for Rust and we would do better to
achieve parallel execution through composition. However when it comes to &lt;em&gt;task
scheduling&lt;&#x2F;em&gt; things seem less clear, and I would like to have more data
available.  Because task scheduling strategies determine which APIs we can
provide, and as we&#x27;re looking to standardize the async Rust ecosystem, this will
end up being important.&lt;&#x2F;p&gt;
&lt;p&gt;So okay, big claim - &lt;em&gt;&quot;Tasks are not the wrong abstraction&quot;&lt;&#x2F;em&gt;. Tasks are a staple
in async Rust (and I should know), and task spawning has been around pretty much
since the beginning. However, two relatively recent developments have made me
start to question whether tasks themselves actually carry their weight, both for
single-threaded concurrent workloads and parallel multi-threaded workloads:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Both Bytedance&#x27;s (TikTok&#x27;s) &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytedance&#x2F;monoio&quot;&gt;&lt;code&gt;monoio&lt;&#x2F;code&gt;
crate&lt;&#x2F;a&gt; and the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytedance&#x2F;monoio&#x2F;blob&#x2F;085bafcec6f718370c75c5e7a78423c8b090911e&#x2F;docs&#x2F;en&#x2F;benchmark.md&quot;&gt;&lt;code&gt;glommio&lt;&#x2F;code&gt;
crate&lt;&#x2F;a&gt;
use a thread-per-core architecture and appear to scale significantly better than
Tokio&#x27;s work-stealing architecture on
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytedance&#x2F;monoio&#x2F;blob&#x2F;085bafcec6f718370c75c5e7a78423c8b090911e&#x2F;docs&#x2F;en&#x2F;benchmark.md&quot;&gt;networking benchmarks&lt;&#x2F;a&gt;.
&lt;strong&gt;This raises questions about tasks as primitives for parallel async
execution.&lt;&#x2F;strong&gt; (edit: I mean &quot;questions&quot; literally here - these are interesting
claims which we should research more closely. We get into that more later on in
this post).&lt;&#x2F;li&gt;
&lt;li&gt;Single-threaded executors introduce &lt;code&gt;&#x27;static&lt;&#x2F;code&gt; lifetimes, often do not
correctly propagate errors and cancellation, and in recent testing have shown to
perform &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;smol-rs&#x2F;futures-lite&#x2F;issues&#x2F;93#issuecomment-2007937805&quot;&gt;up to 2-3x
worse&lt;&#x2F;a&gt;
than their structured counterparts. We have alternative APIs available for
concurrency which do not have these issues. &lt;strong&gt;This raises questions about tasks
as primitives for concurrent async execution.&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;In this post I want to discuss task spawning for just concurrent but also
parallel execution. I want to show some of the issues both of these approaches
run into, show how we can do better, and talk about what we need more data on.
Finally I want to speculate a little about where we could go with async
parallelism and concurrency in Rust. But to save everyone some reading, here&#x27;s
some code roughly summarizing the first half of this post &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#structure&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;structure&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Note that the third example here says: &quot;structured&quot;. What I
actually mean is: as structured as is possible when working within the current
limitations of the language. But this API would be entirely structured if we
didn&#x27;t have those limitations.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; concurrent execution of two futures today (structured)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = async { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;};              &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← does nothing until .awaited
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = async { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;};              &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← does nothing until .awaited
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(a, b) = (a, b).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;().await; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← concurrent `.await`
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; parallel execution of two futures today (unstructured)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = async_std::spawn(async { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;});  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← begins parallel execution when created
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = async_std::spawn(async { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;});  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← begins parallel execution when created
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = a.await;                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← await order does not affect execution
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = b.await;                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← await order does not affect execution
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; parallel execution of two futures as proposed (structured)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = async { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;}.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;par&lt;&#x2F;span&gt;&lt;span&gt;();         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← does nothing until .awaited
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = async { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;}.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;par&lt;&#x2F;span&gt;&lt;span&gt;();         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← does nothing until .awaited
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(a, b) = (a, b).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;().await;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← parallel `.await`
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;preface-concurrent-and-parallel-execution&quot;&gt;Preface: concurrent and parallel execution&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Note (2024-04-27): this section was added after repeated questions about the
difference between parallelism and concurrency.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In order to make sense of this post, it&#x27;s important to understand the
differences between parallelism and concurrency, as well as parallel execution
and concurrent execution. These are related but distinct terms, and it can take
some time to internalize. My favorite definition of the differences between
these comes from &lt;a href=&quot;http:&#x2F;&#x2F;aturon.github.io&#x2F;academic&#x2F;turon-thesis.pdf&quot;&gt;Aaron Turon&#x27;s PhD
thesis&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Concurrency is a system-structuring mechanism, parallelism is a resource.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Put concretely: &quot;concurrency&quot; refers to the way we schedule work. While
&quot;parallelism&quot; refers to e.g. the amount of cores a computer has. If we want to
perform &lt;em&gt;parallel execution of work&lt;&#x2F;em&gt;, we have to schedule work concurrently
using the system&#x27;s resources for parallelism. We can plot the relationship of
parallelism and concurrency in a 2x2 table:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;no parallelism&lt;&#x2F;th&gt;&lt;th&gt;has parallelism&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;sequential scheduling&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;sequential execution&lt;&#x2F;td&gt;&lt;td&gt;sequential execution&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;concurrent scheduling&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;concurrent execution&lt;&#x2F;td&gt;&lt;td&gt;parallel execution&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;This table is probably going to surprise some folks. What we&#x27;re seeing here is
that even if we use multiple threads, it&#x27;s still possible to achieve
&lt;em&gt;sequential&lt;&#x2F;em&gt; execution. How can that be? Well dear reader, imagine some
exclusive resource shared between N threads. In order for any thread to make
progress they must take an exclusive lock out on that resource. That would
certainly make use of multiple threads; but execution would be entirely
sequential - only one thread can make progress at any given moment. In order to
achieve &lt;em&gt;parallel execution&lt;&#x2F;em&gt; it&#x27;s not enough to just make use of &lt;em&gt;parallelism&lt;&#x2F;em&gt;;
we also have to schedule concurrently.&lt;&#x2F;p&gt;
&lt;p&gt;Conversely it&#x27;s also possible to schedule work concurrently despite not having
access to any parallelism. An example of this is for example: race two timers
with each other. We&#x27;re waiting on both at the same time, despite not having
multiple threads. This is an example of &lt;em&gt;concurrent execution&lt;&#x2F;em&gt; without any
access to resources for parallelism.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tasks-are-the-wrong-abstraction-for-parallel-async-execution&quot;&gt;Tasks are the wrong abstraction for parallel async execution&lt;&#x2F;h2&gt;
&lt;p&gt;Cq. 2019 I helped popularize the reasoning that: &lt;em&gt;&quot;Tasks should function like
the &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; equivalent of threads&quot;&lt;&#x2F;em&gt;. Among other things that meant that
in the &lt;code&gt;runtime&lt;&#x2F;code&gt; crate and subsequently &lt;code&gt;async-std&lt;&#x2F;code&gt; we made sure that tasks
always returned &lt;code&gt;JoinHandle&lt;&#x2F;code&gt;s, and that those handles could be awaited to obtain
values. Prior to that it was common to manually create async one-shot channels
to obtain values from tasks
(&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;juliex&#x2F;0.3.0-alpha.8&#x2F;juliex&#x2F;fn.spawn.html&quot;&gt;src&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#juliex&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;):&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;juliex&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Romio and Juliex were the reactor and executor Boats and I worked on
between 2018-2019. It&#x27;s a pretty good snapshot of what the state of the art of
APIs looked like back then.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! What using tasks was like cq. December 2018
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::thread;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures::{executor, channel::oneshot};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; handles = vec![];
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;_ in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(sender, receiver) = oneshot::channel();
&lt;&#x2F;span&gt;&lt;span&gt;        handles.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(receiver);
&lt;&#x2F;span&gt;&lt;span&gt;        juliex::spawn(async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; id = thread::current().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;            sender.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(id);
&lt;&#x2F;span&gt;&lt;span&gt;        })
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; handler in handles {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; id = handler.await; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; this was actually `await!` then.
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;handler returned from thread: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{id:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That rationale that &lt;em&gt;&quot;tasks are like async threads&quot;&lt;&#x2F;em&gt; has stuck around, and I
think it is wrong. See, concurrency and parallelism in async Rust are different
than in non-async Rust. The &lt;code&gt;Thread&lt;&#x2F;code&gt; abstraction packages both &lt;em&gt;concurrency&lt;&#x2F;em&gt; and
&lt;em&gt;parallelism&lt;&#x2F;em&gt; into a single abstraction. Whereas in async Rust the two can be
decoupled: we can execute any number of futures concurrently, and we don&#x27;t need
to also make us of parallelism for it. Let&#x27;s walk through some examples,
starting with parallel execution using unstructured thread handles:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::thread;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; handles = vec![];
&lt;&#x2F;span&gt;&lt;span&gt;handles.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(thread::spawn(|| {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← the result of some computation
&lt;&#x2F;span&gt;&lt;span&gt;}));
&lt;&#x2F;span&gt;&lt;span&gt;handles.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(thread::spawn(|| {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← the result of another computation
&lt;&#x2F;span&gt;&lt;span&gt;}));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; output = handles.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;h&lt;&#x2F;span&gt;&lt;span&gt;| h.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;()).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(output, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Rust does not provide us with a way to say that no, we don&#x27;t actually want to
leverage parallelism here - we just want concurrency. That&#x27;s why &lt;code&gt;thread::spawn&lt;&#x2F;code&gt;
always takes a &lt;code&gt;+ Send&lt;&#x2F;code&gt; bound on the closure. In async Rust however, we can just
choose to execute work concurrently via the &lt;code&gt;Join&lt;&#x2F;code&gt; family of APIs. Here&#x27;s an
example using &lt;code&gt;futures-concurrency&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_concurrency::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; handles = vec![];
&lt;&#x2F;span&gt;&lt;span&gt;handles.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(async {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← the result of some computation
&lt;&#x2F;span&gt;&lt;span&gt;}));
&lt;&#x2F;span&gt;&lt;span&gt;handles.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(async {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← the result of another computation
&lt;&#x2F;span&gt;&lt;span&gt;}));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; output = handles.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;().await.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(output, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Structurally this is very similar to the unstructured threads example; however
because futures are lazy and automatically propagate cancellation, they can be
considered structured &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#modulo&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Though typically we&#x27;d probably write this
example like this instead:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;modulo&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;I&#x27;ve gone into details about the limitations of structured concurrency in Rust today in other posts. TLDR: we need an async version of &lt;code&gt;Drop&lt;&#x2F;code&gt; to actually solve all cases.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_concurrency::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = async { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = async { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; output = (a, b).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;().await.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← executes futures concurrently
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(output, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now what about parallelism? Well, the point I&#x27;m trying to make is that we can
achieve parallel execution through &lt;em&gt;composition&lt;&#x2F;em&gt; rather than defining new APIs.
It&#x27;s common practice today to resort to &lt;code&gt;task::spawn&lt;&#x2F;code&gt; APIs for this, mirroring
the &lt;code&gt;thread::spawn&lt;&#x2F;code&gt; APIs:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::task;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; handles = vec![];
&lt;&#x2F;span&gt;&lt;span&gt;handles.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(task::spawn(async {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← the result of some computation
&lt;&#x2F;span&gt;&lt;span&gt;}));
&lt;&#x2F;span&gt;&lt;span&gt;handles.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(task::spawn(async {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← the result of another computation
&lt;&#x2F;span&gt;&lt;span&gt;}));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; output = handles.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;h&lt;&#x2F;span&gt;&lt;span&gt;| h.await).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(output, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There&#x27;s a pretty noticeable difference between the previous two examples: one
family of async APIs for concurrency, and another family of APIs for both
concurrency and parallelism. My pitch here is different: I believe the right way
to achieve parallel execution is through &lt;em&gt;composition&lt;&#x2F;em&gt;. What we need is not
another way to schedule async work; what we need is a way to define a
&lt;em&gt;parallelizable future&lt;&#x2F;em&gt;. And that&#x27;s something I&#x27;ve prototyped in my &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tasky&quot;&gt;&lt;code&gt;tasky&lt;&#x2F;code&gt;
*crate&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_concurrency::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;tasky::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = async { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;}.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;par&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← added `.par` to create a `ParallelFuture`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = async { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;}.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;par&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← added `.par` to create a `ParallelFuture`
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; output = (a, b).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;().await.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← executes two futures in parallel
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(output, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This approach makes it so we have one way of scheduling concurrent execution,
and resources themselves are responsible for deciding whether they should be
parallelizable or not. Again: &lt;strong&gt;async Rust allows us to decouple parallelism
from concurrency in ways not possible in non-async Rust; and so we should design
our APIs in ways which leverage that decoupling.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;With &lt;code&gt;ParallelizableFuture&lt;&#x2F;code&gt; work doesn&#x27;t start until it is first &lt;code&gt;.await&lt;&#x2F;code&gt;ed.
This makes it behave just like any other future. Unlike task handles you can&#x27;t
just fire and forget it; you have to be actively &lt;code&gt;.await&lt;&#x2F;code&gt;ing it to make forward
progress. That means a value is always returned, and cancellation will always
propagate. And once we have async destructors, those should be able to naturally
propagate through the &lt;code&gt;.await&lt;&#x2F;code&gt; points too. This is an API which should be
familiar to use, but hard to misuse. It&#x27;s setting people up for success when it
comes to things like propagating cancellation and learning about async
concurrency.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tasks-are-the-wrong-abstraction-for-concurrent-async-execution&quot;&gt;Tasks are the wrong abstraction for concurrent async execution&lt;&#x2F;h2&gt;
&lt;p&gt;This point is probably easier to argue than the previous one: using &lt;code&gt;spawn&lt;&#x2F;code&gt; APIs
for just concurrency without also leveraging parallelism is generally not a
great experience. Consider the following example, using &lt;code&gt;task::spawn_local&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::task;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; handles = vec![];
&lt;&#x2F;span&gt;&lt;span&gt;handles.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(task::spawn_local(async {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← the result of some computation
&lt;&#x2F;span&gt;&lt;span&gt;}));
&lt;&#x2F;span&gt;&lt;span&gt;handles.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(task::spawn_local(async {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← the result of another computation
&lt;&#x2F;span&gt;&lt;span&gt;}));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; output = handles.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;h&lt;&#x2F;span&gt;&lt;span&gt;| h.await).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(output, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This now does the exact same thing as our earlier &lt;code&gt;Join&lt;&#x2F;code&gt; example, except it
needs to allocate space on the heap to store each individual future. That&#x27;s a
flat performance tax each task needs to pay; and in this case we&#x27;ve already
shown it&#x27;s avoidable in ever scenario. But that&#x27;s just performance; there are
additional restrictions with regards to ergonomics. The signature of
&lt;code&gt;spawn_local&lt;&#x2F;code&gt; is as follows:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;spawn_local&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;F, T&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;future&lt;&#x2F;span&gt;&lt;span&gt;: F) -&amp;gt; JoinHandle&amp;lt;T&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    F: Future&amp;lt;Output = T&amp;gt; + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    T: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;, 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;&#x27;static&lt;&#x2F;code&gt; lifetime ensures that the future cannot contain any borrows, and
resolving it takes a lot of effort because it isn&#x27;t natural to the language. An
example of this is the &lt;code&gt;moro&lt;&#x2F;code&gt; crate, which provides an API for &quot;scoped
single-threaded tasks&quot; via an &lt;code&gt;async_scope!&lt;&#x2F;code&gt; macro. The macro is necessary
because the lifetimes required for this currently can&#x27;t be expressed in the
language. Here is an adaptation of the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;thread&#x2F;fn.scope.html&quot;&gt;&lt;code&gt;thread::scope&lt;&#x2F;code&gt; example&lt;&#x2F;a&gt; converted to use &lt;code&gt;moro&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; container = vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; num = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;moro::async_scope!(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;| {
&lt;&#x2F;span&gt;&lt;span&gt;    s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(async {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello from the first scoped thread&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;        dbg!(&amp;amp;container);
&lt;&#x2F;span&gt;&lt;span&gt;    });
&lt;&#x2F;span&gt;&lt;span&gt;    s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(async {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello from the second scoped thread&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;        num += container[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] + container[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;    });
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello from the main thread&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}).await;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;container.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(num, container.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s rewrite this using the &lt;code&gt;futures-concurrency&lt;&#x2F;code&gt;, which doesn&#x27;t rely on tasks,
doesn&#x27;t enforce &lt;code&gt;&#x27;static&lt;&#x2F;code&gt; lifetimes, and so in turn can freely express what is
being expressed here:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_concurrency::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; container = vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; num = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = async {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello from the first future&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    dbg!(&amp;amp;container);
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = async {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello from the second future&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    num += container[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] + container[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello from the main future&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;_ = (a, b).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;().await;
&lt;&#x2F;span&gt;&lt;span&gt;container.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(num, container.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are more complex cases possible where we have dynamically updating sets of
futures or streams we want to append to, which we want to manage as a group.
Getting into that here would mean we&#x27;d run long, but for an example of the
problem I&#x27;d like to point to &lt;a href=&quot;https:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2022&#x2F;06&#x2F;13&#x2F;async-cancellation-a-case-study-of-pub-sub-in-mini-redis&#x2F;&quot;&gt;Niko&#x27;s mini-redis
post&lt;&#x2F;a&gt;,
and for an example of how to solve this without tasks or &lt;code&gt;select!&lt;&#x2F;code&gt;, see the
second example of the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-concurrency&#x2F;7.6.0&#x2F;futures_concurrency&#x2F;stream&#x2F;stream_group&#x2F;struct.StreamGroup.html#example&quot;&gt;&lt;code&gt;StreamGroup&lt;&#x2F;code&gt; type&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I realize that by this point we&#x27;ve veered pretty far off the original point of
this section. But it&#x27;s pretty trivial it probably bears repeating: &lt;strong&gt;&lt;code&gt;Tasks&lt;&#x2F;code&gt;
with their &lt;code&gt;&#x27;static&lt;&#x2F;code&gt; bounds and performance overhead seem like a poor fit when
used solely for concurrency.&lt;&#x2F;strong&gt; And while crates like &lt;code&gt;moro&lt;&#x2F;code&gt; can help overcome
some of those challenges, they don&#x27;t do it fully and don&#x27;t appear to provide
additional expressivity.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;stealing-and-sending&quot;&gt;Stealing and sending&lt;&#x2F;h2&gt;
&lt;p&gt;Baked into Rust&#x27;s async design is the assumption that work-stealing schedulers
represent the pinnacle of performance, and therefor it for example makes sense
that &lt;code&gt;Waker&lt;&#x2F;code&gt; must always be &lt;code&gt;Send&lt;&#x2F;code&gt;. Work-stealing allows threads to &quot;steal&quot; work
from other threads when they&#x27;re idle. In case one thread has a lot of work
scheduled, and another thread is free, this is supposed to enable lower
latencies and more throughput.&lt;&#x2F;p&gt;
&lt;p&gt;This not without downsides though: in order to facilitate this, it requires that
every future contained within a task is &lt;code&gt;Send&lt;&#x2F;code&gt;. &lt;strong&gt;The premise of work-stealing
is that the performance gains it provides are more than the performance
penalties we incur from requiring all futures are &lt;code&gt;Send&lt;&#x2F;code&gt;.&lt;&#x2F;strong&gt; Because making
futures &lt;code&gt;Send&lt;&#x2F;code&gt; not only carries a degree of complexity for the language, it also
comes with inherent performance penalties because it requires synchronization.
You know how you can&#x27;t use &lt;code&gt;Rc&lt;&#x2F;code&gt; with &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; - that&#x27;s a direct artifact
of work-stealing designs.&lt;&#x2F;p&gt;
&lt;p&gt;The Glommio and Monoio runtimes put this premise into question. Neither of them
provide a work-stealing runtime, preferring to use a &quot;thread-per-core&quot; design
instead. But by doing this, they do not require to use additional
synchronization primitives, and seem to &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytedance&#x2F;monoio&#x2F;blob&#x2F;085bafcec6f718370c75c5e7a78423c8b090911e&#x2F;docs&#x2F;en&#x2F;benchmark.md&quot;&gt;perform
better&lt;&#x2F;a&gt;
on networked benchmarks than work-stealing runtimes. &lt;strong&gt;Monoio claims 2x the
throughput of Tokio with 4 cores, and 3x the throughput of Tokio with 16
cores.&lt;&#x2F;strong&gt; This is possible because of their thread-per-core design, but likely
also usage of &lt;code&gt;io_uring&lt;&#x2F;code&gt;. I believe we should get updated numbers on this, at least comparing Monoio to the &lt;code&gt;tokio-uring&lt;&#x2F;code&gt; project.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sharded-send-bounds&quot;&gt;Sharded send bounds&lt;&#x2F;h2&gt;
&lt;p&gt;Tmandry raised an interesting idea a while back: using &lt;code&gt;Rc&lt;&#x2F;code&gt; and other &lt;code&gt;!Send&lt;&#x2F;code&gt;
types inside of &lt;code&gt;Send&lt;&#x2F;code&gt; futures should fine, as long as we can guarantee that all
references are moved together as a group. Over in Swift conversations have
recently begun about a feature called &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gottesmm&#x2F;swift-evolution&#x2F;blob&#x2F;4576ac1a0ff8112e69e56bda5fbbc2bd83ea76cc&#x2F;proposals&#x2F;0414-region-based-isolation.md&quot;&gt;Region Based
Isolation&lt;&#x2F;a&gt;,
describing a very similar idea based on the ideas from: &lt;a href=&quot;https:&#x2F;&#x2F;www.cs.cornell.edu&#x2F;andru&#x2F;papers&#x2F;gallifrey-types&#x2F;&quot;&gt;&quot;A Flexible Type System
for Fearless
Concurrency&quot;&lt;&#x2F;a&gt; from
PLDI 2022. The Swift SE describes it as follows:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Through the usage of isolation regions, the language can prove that transferring a non-Sendable value over an isolation boundary cannot result in races because the value (and any other value that might reference it) is not used in the caller after the point of transfer.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Translating this to Rust, I believe it would allow us to do the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; rc = Rc::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← `!Send` type
&lt;&#x2F;span&gt;&lt;span&gt;task::spawn(async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← crossing a `Send` boundary
&lt;&#x2F;span&gt;&lt;span&gt;    dbg!(rc);              &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← all references moved: compiler says OK
&lt;&#x2F;span&gt;&lt;span&gt;}).await;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It makes sense that this is all fine: all references to &lt;code&gt;Rc&lt;&#x2F;code&gt; are moved to a new
thread, so that&#x27;s not an issue. But I don&#x27;t know whether this can hold for all
&lt;code&gt;!Send&lt;&#x2F;code&gt; types. I don&#x27;t think it would be, because occasionally threads will be
&quot;special&quot; and so moving a &lt;code&gt;!Send&lt;&#x2F;code&gt; type to another thread even with all
references might end up with trouble. This likely would require an additional
modifier to &lt;code&gt;Send&lt;&#x2F;code&gt;, integrated through the libraries and possibly language. It&#x27;s
an interesting idea that needs more research before we can consider it viable,
but I wanted to make sure to mention it because it does hold promise.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;parallel-futures-and-send-bounds&quot;&gt;parallel futures and send bounds&lt;&#x2F;h2&gt;
&lt;p&gt;Both Monoio and Glommio provide a local executor as part of their API. Earlier
on in this post I&#x27;ve explained why &quot;local executors&quot; are not a great
abstraction. That&#x27;s why for
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;building-an-async-runtime-for-wasi&#x2F;&quot;&gt;&lt;code&gt;wasi-async-runtime&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;,
which also features a single-threaded runtime, I&#x27;ve chosen not to provide a
&lt;code&gt;spawn&lt;&#x2F;code&gt; API at all. Instead people are encouraged to use libraries such as
&lt;code&gt;futures-concurrency&lt;&#x2F;code&gt; instead.&lt;&#x2F;p&gt;
&lt;p&gt;However, even if work-stealing might not carry its weight in Rust right now, I
think we might still be able to provide a &lt;code&gt;spawn&lt;&#x2F;code&gt; API. That could potentially
even make thread-per-core architectures nicer to express in certain cases where
we want an &lt;code&gt;async fn main&lt;&#x2F;code&gt;. &lt;strong&gt;The choice of whether we believe work-stealing
carries its weight will end up deciding what the right API will be to go with.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;task::spawn&lt;&#x2F;code&gt; API for both Tokio and async-std is quite similar and looks
something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;F, T&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;future&lt;&#x2F;span&gt;&lt;span&gt;: F) -&amp;gt; JoinHandle&amp;lt;T&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    F: Future&amp;lt;Output = T&amp;gt; + Send + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    T: Send + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;, 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It takes a &lt;code&gt;Future&lt;&#x2F;code&gt;, and that &lt;code&gt;Future&lt;&#x2F;code&gt; must be &lt;code&gt;Send&lt;&#x2F;code&gt;. Easy, right? Now what if we compare that with the signature of &lt;code&gt;thread::spawn&lt;&#x2F;code&gt;, which looks like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;F, T&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;: F) -&amp;gt; JoinHandle&amp;lt;T&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    F: FnOnce() -&amp;gt; T + Send + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    T: Send + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here we don&#x27;t have a future, but instead we have a closure. The closure itself
is &lt;code&gt;Send&lt;&#x2F;code&gt;, and the value &lt;code&gt;T&lt;&#x2F;code&gt; is &lt;code&gt;Send&lt;&#x2F;code&gt;. At a glance this might look equivalent
to the &lt;code&gt;task::spawn&lt;&#x2F;code&gt; APIs, but it&#x27;s not. This becomes clearer if we encode the
original API not as taking &lt;code&gt;Future&lt;&#x2F;code&gt;, but instead as taking &lt;code&gt;IntoFuture&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;F, T&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;into_future&lt;&#x2F;span&gt;&lt;span&gt;: F) -&amp;gt; JoinHandle&amp;lt;T&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    F: IntoFuture&amp;lt;Output = T&amp;gt; + Send + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;lt;F as IntoFuture&amp;gt;:IntoFuture: Send + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    T: Send + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;, 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Not only is the thing we pass into the other thread &lt;code&gt;Send&lt;&#x2F;code&gt;; because we want to
allow the ongoing computation itself to be movable between threads the future
itself must also be &lt;code&gt;Send&lt;&#x2F;code&gt;. &lt;code&gt;thread::spawn&lt;&#x2F;code&gt; can use &lt;code&gt;!Send&lt;&#x2F;code&gt; types freely because
once the computation has started, it will not be moved. If we wanted to encode
that, we could do that by changing it to the following signature:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;F, T&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;into_future&lt;&#x2F;span&gt;&lt;span&gt;: F) -&amp;gt; JoinHandle&amp;lt;T&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    F: IntoFuture&amp;lt;Output = T&amp;gt; + Send + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    T: Send + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `F:IntoFuture` is no longer required to be `Send` here
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Whether &lt;code&gt;task::spawn&lt;&#x2F;code&gt; should take &lt;code&gt;Send&lt;&#x2F;code&gt; bounds is a decision we&#x27;re going to
have to make if we want to encode a standardized spawn API in the stdlib. It&#x27;s
not necessarily zero-sum though; we could probably encode both. But so far
evidence seems to indicate that if we want maximum performance thread-per-core
is a better approach; while if we want maximum convenience enabling &lt;code&gt;!Send&lt;&#x2F;code&gt;
types to work inside of parallelizable futures may actually be simpler to use.
More data here would certainly be helpful.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-vision-for-concurrency-and-parallelism-in-rust&quot;&gt;A vision for concurrency and parallelism in Rust&lt;&#x2F;h2&gt;
&lt;p&gt;So far I&#x27;ve asked a number of questions, and probably observed a little too
much. I imagine the average async Rust user will be somewhere between confusion
and morbid curiosity of where I&#x27;m going with all of this. I want to put a rough
sketch forward of where I, Yosh, would like concurrency and parallelism in Rust
to eventually get to. I believe we could get pretty far if we made concurrency
and parallelism first-class concepts in Rust via two new keywords, which we&#x27;ll
call &lt;code&gt;par&lt;&#x2F;code&gt; and &lt;code&gt;co&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Take the venerable Rayon &lt;code&gt;ParallelIterator&lt;&#x2F;code&gt; trait. It allows us to iterate over
items in parallel rather than in sequence. While it works great using combinator
APIs; it does not allow us to use &lt;code&gt;for&lt;&#x2F;code&gt;-loops the way we&#x27;d expect. What if we
could do that by introducing &lt;code&gt;for par..in&lt;&#x2F;code&gt; loops:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;square&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;input&lt;&#x2F;span&gt;&lt;span&gt;: impl Iterator&amp;lt;Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) -&amp;gt; impl Iterator&amp;lt;Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    gen &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← current unstable `gen` block notation
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; par num in input { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← parallel iteration syntax (hypothetical)
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;yield&lt;&#x2F;span&gt;&lt;span&gt; num * num;
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The body of the loop here would be roughly equivalent to Rayon&#x27;s
&lt;code&gt;ParallelIterator::for_each&lt;&#x2F;code&gt; - with the exception that it doesn&#x27;t just loop but
returns an iterator. In async Rust we don&#x27;t yet have async iteration, but we&#x27;re
currently looking at something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;square&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;input&lt;&#x2F;span&gt;&lt;span&gt;: impl async Iterator&amp;lt;Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) -&amp;gt; impl async Iterator&amp;lt;Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    async gen &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{              &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← current unstable `async gen` block notation
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; await num in input {  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← sequential async iteration syntax (likely)
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;yield&lt;&#x2F;span&gt;&lt;span&gt; num * num;
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is all unstable and unconfirmed, but it seems likely things will end up
along these lines. The least certain part is the exact shapes and names of
traits, but that&#x27;s not the important bit here. Now as we&#x27;ve said we can decouple
concurrency and parallelism in async Rust. So what would a concurrent version of
this loop look like? Well, one of the main benefits of async Rust is that we can
run things concurrently - so what if we made that a first-class part of the
language? That&#x27;s what a hypothetical &lt;code&gt;co&lt;&#x2F;code&gt; keyword could be for:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;square&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;input&lt;&#x2F;span&gt;&lt;span&gt;: impl async Iterator&amp;lt;Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) -&amp;gt; impl async Iterator&amp;lt;Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    async gen &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; co await num in input {  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← concurrent async iteration syntax (hypothetical)
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;yield&lt;&#x2F;span&gt;&lt;span&gt; num * num;
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Whether we&#x27;d spell this &lt;code&gt;co.await&lt;&#x2F;code&gt;, &lt;code&gt;co_await&lt;&#x2F;code&gt; or &lt;code&gt;co await&lt;&#x2F;code&gt; doesn&#x27;t
particularly matter. Making concurrency easier to leverage seems like a nice
thing. In terms of implementation we could leverage my recent work on
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yoshuawuyts&#x2F;futures-concurrency&#x2F;releases&#x2F;tag&#x2F;v7.6.0&quot;&gt;&lt;code&gt;ConcurrentStream&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; for this. If
we then wanted to extend this to parallelism too, we could instead use &lt;code&gt;par await&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;square&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;input&lt;&#x2F;span&gt;&lt;span&gt;: impl async Iterator&amp;lt;Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) -&amp;gt; impl async Iterator&amp;lt;Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    async gen &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; par await num in input {  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← parallel async iteration syntax (hypothetical)
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;yield&lt;&#x2F;span&gt;&lt;span&gt; num * num;
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This doesn&#x27;t just need to stop at iterators either; we could integrate this into
futures and &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; too. Not too different from how Swift&#x27;s &lt;code&gt;async let&lt;&#x2F;code&gt;
notation works. Remember our earlier example using &lt;code&gt;futures-concurrency&lt;&#x2F;code&gt; to
evaluate futures concurrently?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_concurrency::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = async { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = async { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; output = (a, b).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;().await.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← executes futures concurrently
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(output, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It would be nice if the compiler could perform control-flow analysis directly,
and for automatically schedule concurrent execution of futures where permitted, as long as they were called with &lt;code&gt;.co.await&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = async { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;}.co.await; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← concurrent await syntax (hypothetical)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = async { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;}.co.await; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← concurrent await syntax (hypothetical)
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(a + b, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And what about parallelism? Well, we should also be able to compose &lt;code&gt;.par&lt;&#x2F;code&gt; with
&lt;code&gt;.await&lt;&#x2F;code&gt; to achieve parallel async execution:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = async { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;}.par.await; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← parallel await syntax (hypothetical)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = async { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;}.par.await; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ← parallel await syntax (hypothetical)
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(a + b, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;One of the main appeals of representing async operations as types is that we can
then arbitrarily combine them with other futures to achieve concurrent
execution. Neither future here needs to be &lt;code&gt;&#x27;static&lt;&#x2F;code&gt; to work with &lt;code&gt;par&lt;&#x2F;code&gt;, and
borrows should just work as expected. &lt;strong&gt;If we are able to bake concurrent and
parallel execution directly into the language, we no longer have to represent
the computation as a type. By making &lt;code&gt;.par&lt;&#x2F;code&gt; a modifier to &lt;code&gt;.await&lt;&#x2F;code&gt;, parallel
futures would not be represented in the type system and we would be able to
solve the scoped parallel async execution problem directly from the language.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Oh and the other nice bonus of this: it would work perfectly with
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;extending-rusts-effect-system&#x2F;&quot;&gt;&lt;code&gt;#[maybe(async)&lt;&#x2F;code&gt;]&lt;&#x2F;a&gt;
function bodies, as we can always fall back from concurrent semantics in async
contexts to sequential semantics in non-async contexts. There is probably also
something interesting to be said about bare &lt;code&gt;par {}&lt;&#x2F;code&gt; blocks and scoped threads,
but that&#x27;s out of scope (૮꒰ ˶• ༝ •˶꒱ა) for now.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve jumped around a fair bit. You would be forgiven for having
some trouble following all threads and ideas. But let me try and summarize the
arguments I&#x27;ve attempted to make:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Tasks are a poor fit for non-parallel concurrent execution.&lt;&#x2F;strong&gt; They come with
additional performance overhead and impose &lt;code&gt;&#x27;static&lt;&#x2F;code&gt; lifetime restrictions,
creating knock-on problems.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Tasks are a poor fit for parallel concurrent execution.&lt;&#x2F;strong&gt; They are presently
designed to function as &quot;async&#x2F;.await&quot; versions of threads. And as a result
combine both concurrency and parallelism into a single API. Instead we would do
better to provide a &lt;code&gt;ParallelFuture&lt;&#x2F;code&gt; type which provides parallel execution
through &lt;em&gt;composition&lt;&#x2F;em&gt; with concurrency primitives.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;The success of the Monoio and Glommio runtimes are putting into question whether
work-stealing executors are the right fit.&lt;&#x2F;strong&gt; They show significant performance
improvements over work-stealing by leveraging a thread-per-core architecture. We
need more data to understand the differences before we can make decisions.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Deciding between thread-per-core and work-stealing executors has
ramifications for what &lt;code&gt;spawn&lt;&#x2F;code&gt; APIs should look like.&lt;&#x2F;strong&gt; Work-stealing executors
can&#x27;t capture &lt;code&gt;!Send&lt;&#x2F;code&gt; types, while non-work-stealing executors can operate on
&lt;code&gt;!Send&lt;&#x2F;code&gt; types.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;There might be benefits to elevating concurrency and parallelism primitives
from the libraries into the language.&lt;&#x2F;strong&gt; Fast, safe, concurrent execution is Rust&#x27;s
flagship feature, and making that more accessible would likely pay dividends.
This would also provide an alternative way of expressing &quot;scoped tasks&quot;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;I hope that if you take anything away from this post it&#x27;s some of the ground
truths of async Rust may be less set in stone than you expected them to be.
There definitely appear to be tradeoffs between the various task scheduling
approaches and designs, and I don&#x27;t think we should just assume that
work-stealing is the better approach. What we really need is a better
understanding of the tradeoffs involved, and for that we&#x27;re going to need data.
Deciding without measuring is not going to work.&lt;&#x2F;p&gt;
&lt;p&gt;Oh also: &lt;strong&gt;we cannot provide standardized async APIs for parallelism without
first stabilizing async destructors.&lt;&#x2F;strong&gt; I find myself repeating this so often I
feel like a walking meme at this point. Without async destructors so much of
async Rust is broken, and we cannot stabilize interfaces before we know how
async destructors will interact with them. Async parallelism specifically is
also &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;tree-structured-concurrency&#x2F;&quot;&gt;extra-broken&lt;&#x2F;a&gt;.
Async Rust is the flagship feature of priority for Rust as a language, and async
closures + async destructors is where we should be spending our time as they&#x27;re
fundamental building blocks.&lt;&#x2F;p&gt;
&lt;p&gt;And on a closing note: I just want to put out there that we should dare to
dream beyond the mere ossification of the status quo. Better things are
possible, as long as we take care of each other and are willing to put in the
work. I regularly tell myself this; and now I&#x27;m it to you too.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Shipping Jco 1.0, WASI 0.2</title>
            <pubDate>Wed, 03 Apr 2024 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/jco-1-0-wasi-0-2/</link>
            <guid>https://blog.yoshuawuyts.com/jco-1-0-wasi-0-2/</guid>
            <description>&lt;p&gt;On this blog I usually post about technical explorations in programming
languages, API design, asynchronous computing, and so on. More recently I&#x27;ve
re-started my work on WebAssembly, WASI, and their integration with Rust. I
expect that work to eventually become more technical again; but my involvement
there for the past year has mostly been focused on process and people. And I
wanted to take a brief moment to talk about it, because that&#x27;s the kind of work
that&#x27;s often easily overlooked. And I&#x27;d like to take a little victory lap for a
second (as a treat).&lt;&#x2F;p&gt;
&lt;p&gt;I can proudly say: I helped ship &lt;a href=&quot;https:&#x2F;&#x2F;bytecodealliance.org&#x2F;articles&#x2F;WASI-0.2&quot;&gt;WASI
0.2&lt;&#x2F;a&gt;! Not just a part of it, but
I helped make sure we worked through the last key blocker. And mostly on time
at that &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#time&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;! And I&#x27;m super proud of it! The entire project was an incredible
team effort - it&#x27;s hard to understate how hard everyone involved has worked on
this. And around five years in the making too. My involvement with the actual
design and implementation was minimal, and I was mostly involved in the second
half of that period. But I can say I&#x27;ve helped in the following ways:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;time&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;When first asked to provide estimates I said something along the lines
of: &lt;em&gt;&quot;I expect we&#x27;ll be able to ship in late November at the soonest, but most
likely December. December will be tricky because of holidays, but I don&#x27;t think
we&#x27;ll slip past January.&quot;&lt;&#x2F;em&gt; And Jco ended up being ready in mid-January, with
WASI 0.2 shipping on January 25th. I think that counts as &lt;em&gt;mostly&lt;&#x2F;em&gt; on time,
right?&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Helped ship Jco 1.0&lt;&#x2F;strong&gt;: Jco is a native JavaScript WebAssembly toolchain and
runtime built for Wasm Components and WASI 0.2. I wrote a blog post about what
it is and how to use it on the &lt;a href=&quot;https:&#x2F;&#x2F;bytecodealliance.org&#x2F;articles&#x2F;jco-1.0&quot;&gt;Bytecode Alliance
blog&lt;&#x2F;a&gt;. I basically stepped into
the role of PM on that project, ensuring we had clearly defined acceptance
criteria to be able to say: &quot;this thing truthfully implements WASI 0.2&quot;. And
then ended up helping make sure we ended up meeting those criteria. This was
my first time donning the PM hat on someone else&#x27;s project. But that&#x27;s what
was needed, so I was happy to take that on.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Helped ship WASI 0.2&lt;&#x2F;strong&gt;: WASI 0.2 is a rebase of the WebAssembly System
Interface onto the WebAssembly Components specification. You can read the
announcement post &lt;a href=&quot;https:&#x2F;&#x2F;bytecodealliance.org&#x2F;articles&#x2F;WASI-0.2&quot;&gt;here&lt;&#x2F;a&gt;.
Wasmtime had full support for WASI 0.2, I want to say, around September 2023.
But in order to ratify the actual specification it needed at least two
conforming implementations. My JS days are long behind me; but Jco was the
best candidate to ship a second conforming implementation. So I figured I&#x27;d do
what needed to be done, and stepped up to help make sure it shipped. And in
the same meeting we announced Jco had started meeting the conformance
criteria, the WASI subgroup committee voted to ratify the WASI 0.2
specification.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Made the case for a basic async model&lt;&#x2F;strong&gt;: One of the biggest limitations of
WASI 0.1 was that it wasn&#x27;t really suited to write networked applications with.
I think it was in 2022 that I started making the case that WASI 0.2 probably
should ship with &lt;em&gt;some&lt;&#x2F;em&gt; way to support asynchronous sockets if we wanted
people to actually use it for server programming. And we shouldn&#x27;t wait for a
future WASI 0.3 to add that potentially years down the line. And that&#x27;s what we actually
ended up shipping: WASI 0.2 supports async sockets and async HTTP via a
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;building-an-async-runtime-for-wasi&#x2F;&quot;&gt;poll-based
interface&lt;&#x2F;a&gt;,
making it possible to write asynchronous networked applications &lt;em&gt;today&lt;&#x2F;em&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#wasi-03&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Helped ship two new Rust backends&lt;&#x2F;strong&gt;: &quot;new&quot; should be in quotation marks
here - one of the backends is basically a rename. But yeah; I helped ship
support for the renamed &lt;code&gt;wasm32-wasip1&lt;&#x2F;code&gt; target, and the newly introduced
&lt;code&gt;wasm32-wasip2&lt;&#x2F;code&gt; targets. My main contributions here were not so much around
the implementation, but mostly around writing change proposals, talking to
people to help explain the changes and provide assurances, and navigating
various organizational challenges. But it&#x27;s happened, and bar any unexpected
issues they should be on the stable channels in a few weeks time! Expect a
blog post about this with details on the Rust internals blog soon. (I&#x27;m
currently procrastinating finishing that one by writing this instead - sorry
everyone.)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Supported people&lt;&#x2F;strong&gt;: Usually I wouldn&#x27;t make mention of this as a noteworthy
contribution. But there&#x27;s talking with people and there&#x27;s
&lt;em&gt;talking&lt;&#x2F;em&gt; with people. And over the past two years I&#x27;ve spent a non-trivial
amount of time talking with people, listening to what they had to say, and
just trying to be there for them. Wasm and WASI are incredibly ambitious
projects. I&#x27;d roughly describe the work as: imagine being tasked
with building several new compilers, defining multiple new operating systems,
creating a mix of novel programming language(s) and a shared ABI. Then take
all of that and make sure it performs at near-native speeds, is able to be
compiled to by virtually every existing programming language, and is usable by non-experts. Then base the
entire thing on a capability-based security model and ensure it is perfectly
sandboxed by default. Finally, all of that technical work gets compacted into
a pressure cooker together with corporate politics, tightening deadlines, and
the pressures of working in open source and open standards. Pandemic.
Layoffs. Burnout. I hope it&#x27;s not hard to see why that ends up being A Lot.
If there&#x27;s any takeaway here: sometimes the best open source contribution anyone
can make is just to sit and listen to what people have to say.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;wasi-03&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;WASI 0.3&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=y3x4-nQeXxc&quot;&gt;async
model&lt;&#x2F;a&gt; is going to be an enormous
step up from the current status quo though - and timing-wise the work on that
seems to be developing faster than people anticipated. However back in 2022, I
was worried that if WASI 0.2 didn&#x27;t ship with async support, there would be a
chance adoption would be too slow to make it to WASI 0.3. The state now is that
key industry use cases are unlocked by WASI 0.2, and WASI 0.3 is mainly about
making that work better and faster. And at least to me so far this seems to have
been the right approach.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;And that&#x27;s it. Unfortunately no cool type theory bits in this post (I like those
a lot; I &lt;em&gt;will&lt;&#x2F;em&gt; talk about type systems for hours if left unchecked) - but I still
wanted to share a little bit about my other recent work. I often catch myself in
the mindset that if I&#x27;m not directly coding or designing features, it doesn&#x27;t
actually count as having worked on something. But that&#x27;s probably unfair to
myself: I ended up spending several hundred hours doing useful work to help ship
WASI 0.2. And I believe I&#x27;ve actually managed to move the needle on getting WASI
in people&#x27;s hands sooner. Doing things I wasn&#x27;t necessarily the most comfortable
with, but it ended up working out! And while I&#x27;m not usually one to gloat, I
felt like maybe, perhaps, I do get to gloat a little about this.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;d also be remiss if I didn&#x27;t point out that the folks in both the WASI
subgroup committee and in the Bytecode Alliance are such a pleasure to work
with. People regularly talk about how smart they are, and the quality of the
work they produce - but I&#x27;d like to instead emphasize just how kind and caring
they are. Talented people, unafraid to dream big, who care about both their
work and each other. WASI 0.2 and Wasm Components are incredibly impressive, and
over the next 6-12 months we&#x27;re going start seeing the first results of the
impact it will have in the space of applied computing.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#hype&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;hype&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;To provide an early taste: &lt;a href=&quot;https:&#x2F;&#x2F;www.globenewswire.com&#x2F;news-release&#x2F;2024&#x2F;03&#x2F;13&#x2F;2845676&#x2F;0&#x2F;en&#x2F;Fermyon-Delivers-the-First-WebAssembly-Platform-for-Kubernetes-Enabling-50x-More-Applications-Per-Node.html&quot;&gt;this
headline&lt;&#x2F;a&gt;
will probably read like marketing hypeware to most people; some company you&#x27;ve
likely never heard of claiming order-of-magnitude improvements in a mature
technology. But the technical work underpinning it is legit. And while I&#x27;m not
in a position to vet the exact claims made, they don&#x27;t at all seem out of line
with what I&#x27;ve seen WASI being able to do so far. I expect similar headlines are
going to keep following now that WASI 0.2 has been ratified and is starting to
be deployed to production. Exciting times!&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</description>
        </item>
        <item>
            <title>Designing an Async Runtime for WASI 0.2</title>
            <pubDate>Thu, 29 Feb 2024 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/building-an-async-runtime-for-wasi/</link>
            <guid>https://blog.yoshuawuyts.com/building-an-async-runtime-for-wasi/</guid>
            <description>&lt;p&gt;In 2019 Stjepan Glavina and I developed the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&quot;&gt;&lt;code&gt;async-std&lt;&#x2F;code&gt;
runtime&lt;&#x2F;a&gt;. That was an off-shoot from the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;runtime&quot;&gt;&lt;code&gt;runtime&lt;&#x2F;code&gt;
project&lt;&#x2F;a&gt;, which itself was an attempt to make it easier
to abstract over different async runtimes. One of the things I&#x27;m most proud of
in the work I did on &lt;code&gt;async-std&lt;&#x2F;code&gt; is the core IO abstraction which Stjepan later
factored out into the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;polling&quot;&gt;&lt;code&gt;polling&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;smol-rs&#x2F;async-io&quot;&gt;&lt;code&gt;async-io&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; libraries as part of
the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;smol&quot;&gt;&lt;code&gt;smol&lt;&#x2F;code&gt; project&lt;&#x2F;a&gt;, where he took them beyond my initial
prototype code into robust building blocks which can work on their own.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, that little stroll down memory lane serves a purpose: I just finished
building &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;wasi-async-runtime&#x2F;latest&#x2F;wasi_async_runtime&#x2F;&quot;&gt;Yet Another Async
runtime&lt;&#x2F;a&gt;. Not to
tell people to actually go and use this - but intended to be more like a working, minimal, but
also correct implementation of an async runtime for &lt;a href=&quot;https:&#x2F;&#x2F;bytecodealliance.org&#x2F;articles&#x2F;WASI-0.2&quot;&gt;WASI
0.2&lt;&#x2F;a&gt;. The purpose of this post
is to detail how I built it, so
you can build your own (if you want to). I&#x27;m one of the first to write this
code, and maybe even the first to write a dedicated runtime, which means that if
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;smol&#x2F;latest&#x2F;smol&#x2F;&quot;&gt;Smol&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;monoio&#x2F;latest&#x2F;monoio&#x2F;&quot;&gt;Monoio&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;glommio&#x2F;latest&#x2F;glommio&#x2F;&quot;&gt;Glommio&lt;&#x2F;a&gt;, or
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio&#x2F;latest&#x2F;tokio&#x2F;&quot;&gt;Tokio&lt;&#x2F;a&gt; want to add support for WASI 0.2
they&#x27;re going to have to implement what I already implemented. So I figured I
might save folks some trouble, and document the work I just finished doing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-wasi-0-2-polling-model&quot;&gt;The WASI 0.2 polling model&lt;&#x2F;h2&gt;
&lt;p&gt;WASI 0.2 is readiness-based rather than completion-based. That means we wait for
the host system to tell us we&#x27;re ready to take an action, rather than wait for
the host system that an action has successfully completed (completion-based).
WASI 0.3 will likely switch to a completion-based system because &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Io_uring&quot;&gt;Linux
&lt;code&gt;io_uring&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;ioringapi&#x2F;&quot;&gt;Windows&#x27;
&lt;code&gt;ioringapi&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; are
completion-based and perform really well, but we don&#x27;t have that yet.&lt;&#x2F;p&gt;
&lt;p&gt;The core polling system in WASI consists of two components: the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;wasi&#x2F;latest&#x2F;wasi&#x2F;io&#x2F;poll&#x2F;struct.Pollable.html&quot;&gt;&lt;code&gt;Pollable&lt;&#x2F;code&gt;
type&lt;&#x2F;a&gt; and the
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;wasi&#x2F;latest&#x2F;wasi&#x2F;io&#x2F;poll&#x2F;fn.poll.html&quot;&gt;&lt;code&gt;poll&lt;&#x2F;code&gt; function&lt;&#x2F;a&gt;. The
&lt;code&gt;Pollable&lt;&#x2F;code&gt; type represents &quot;interest&quot; in an event. Say we had some kind of
&lt;code&gt;read&lt;&#x2F;code&gt; call; there would be an associated &lt;code&gt;Pollable&lt;&#x2F;code&gt; for that call, which we
could submit to the host to say: &quot;please let me know when there&#x27;s a reason for
me to call &lt;code&gt;read&lt;&#x2F;code&gt;&quot;. This is the &quot;readiness&quot; part of the system - you submit your
interest in an operation to the host system, and then the host system will
periodically yield a list of which operations are good to be called. The way to
schedule that interest is via the &lt;code&gt;poll&lt;&#x2F;code&gt; function.&lt;&#x2F;p&gt;
&lt;p&gt;A key difference between the &lt;code&gt;epoll&lt;&#x2F;code&gt; and WASI 0.2&#x27;s &lt;code&gt;poll&lt;&#x2F;code&gt; model is that in WASI
we don&#x27;t schedule interest in &lt;em&gt;resources&lt;&#x2F;em&gt; (e.g. file descriptors), but we
schedule interest in concrete operations. Under &lt;code&gt;epoll&lt;&#x2F;code&gt; we&#x27;d tell the kernel
something like: &quot;hey, here&#x27;s an fd representing some socket - I&#x27;m interested
anytime I can read or write new data to it&quot;. In WASI we&#x27;re more precise; we make
a specific method call, which returns a type. That type will have some way to
get the underlying data, but also a method &lt;code&gt;subscribe&lt;&#x2F;code&gt; which returns a pollable.
We&#x27;re then supposed to wait for the &lt;code&gt;poll&lt;&#x2F;code&gt; call to tell us that the &lt;code&gt;Pollable&lt;&#x2F;code&gt;
is ready - and then we can call the method to get the underlying data without it
returning an error. That&#x27;s probably a lot of words, so here&#x27;s a basic example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;wasi::http::outgoing_handler::{handle, OutgoingRequest};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;wasi::http::types::{Fields, Method, Scheme};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;wasi::io::poll;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Construct an HTTP request
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; fields = Fields::new();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; req = OutgoingRequest::new(fields);
&lt;&#x2F;span&gt;&lt;span&gt;    req.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;set_method&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;Method::Get).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    req.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;set_scheme&lt;&#x2F;span&gt;&lt;span&gt;(Some(&amp;amp;Scheme::Https)).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    req.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;set_path_with_query&lt;&#x2F;span&gt;&lt;span&gt;(Some(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    req.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;set_authority&lt;&#x2F;span&gt;&lt;span&gt;(Some(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;example.com&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Send the request and wait for it to complete
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;handle&lt;&#x2F;span&gt;&lt;span&gt;(req, None).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 1. We&amp;#39;re ready to send the request over the network
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; pollable = res.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;subscribe&lt;&#x2F;span&gt;&lt;span&gt;();        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 2. We obtain the `Pollable` from the response future
&lt;&#x2F;span&gt;&lt;span&gt;    poll::poll(&amp;amp;[&amp;amp;pollable]);              &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 3. Block until we&amp;#39;re ready to look at the response
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; We&amp;#39;re now ready to try and access the response headers. If
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; the request was unsuccessful we might still get an error here,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; but we won&amp;#39;t get an error that we tried to read data before the
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; operation was completed.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = res.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(name, _) in res.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;headers&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;entries&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;header: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{name}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When run via
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytecodealliance&#x2F;cargo-component&quot;&gt;cargo-component&lt;&#x2F;a&gt; (and the
&lt;code&gt;-- -S http&lt;&#x2F;code&gt; flag is passed), this should print the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;header: age
&lt;&#x2F;span&gt;&lt;span&gt;header: cache-control
&lt;&#x2F;span&gt;&lt;span&gt;header: content-type
&lt;&#x2F;span&gt;&lt;span&gt;header: date
&lt;&#x2F;span&gt;&lt;span&gt;header: etag
&lt;&#x2F;span&gt;&lt;span&gt;header: expires
&lt;&#x2F;span&gt;&lt;span&gt;header: last-modified
&lt;&#x2F;span&gt;&lt;span&gt;header: server
&lt;&#x2F;span&gt;&lt;span&gt;header: vary
&lt;&#x2F;span&gt;&lt;span&gt;header: x-cache
&lt;&#x2F;span&gt;&lt;span&gt;header: content-length
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;designing-the-poller-abstraction&quot;&gt;Designing the poller abstraction&lt;&#x2F;h2&gt;
&lt;p&gt;In the HTTP request example we&#x27;ve shown how to make a single HTTP request and
registered that one operation with the &lt;code&gt;poll&lt;&#x2F;code&gt; call. One of the main benefits of
async computing is the ability to perform &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;why-async-rust&#x2F;#ad-hoc-concurrency&quot;&gt;ad-hoc
concurrency&lt;&#x2F;a&gt;:
we don&#x27;t just want to be able to wait for the one operation to complete; we want
to be able to wait on any number of operations to complete &lt;em&gt;at the same time&lt;&#x2F;em&gt;.
This is why the &lt;code&gt;poll&lt;&#x2F;code&gt; function takes a list of &lt;code&gt;Pollable&lt;&#x2F;code&gt; types, and returns a
list of which ones are ready to continue doing work.&lt;&#x2F;p&gt;
&lt;p&gt;For that we need to create some type which can hold the pollables for us, be
somewhat efficient about it, and allow us to associate the list of &quot;ready&quot;
events with some notion of identity. This is important because we&#x27;re building a
runtime for async Rust, which requires that we associate &quot;readiness events&quot; with
&quot;calls to specific
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;task&#x2F;struct.Waker.html&quot;&gt;wakers&lt;&#x2F;a&gt;&quot;. We can begin by
defining a struct containing a &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;slab&#x2F;latest&#x2F;slab&#x2F;&quot;&gt;slab&lt;&#x2F;a&gt;. This
is an efficient key-value data structure which on entry gives you a key to
access the value. It is unordered and reuses allocations - which is great
because we&#x27;ll be continuously registering and deregistering interest in
different &lt;code&gt;Pollable&lt;&#x2F;code&gt;s.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Debug)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;crate&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Poller {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;crate&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;targets&lt;&#x2F;span&gt;&lt;span&gt;: Slab&amp;lt;Pollable&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Whenever we insert a type into &lt;code&gt;Slab&lt;&#x2F;code&gt; it returns a key of type &lt;code&gt;usize&lt;&#x2F;code&gt;. To make
working with it easier, and make bridging into the WASI world easier, we&#x27;re
going to define our own &lt;code&gt;EventKey&lt;&#x2F;code&gt; type to wrap the keys for us, like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A key representing an entry into the poller
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;repr&lt;&#x2F;span&gt;&lt;span&gt;(transparent)]
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;crate&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;EventKey(pub(crate) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we&#x27;re ready to implement the base CRUD methods on the &lt;code&gt;Poller&lt;&#x2F;code&gt;: &lt;code&gt;new&lt;&#x2F;code&gt;,
&lt;code&gt;insert&lt;&#x2F;code&gt;, &lt;code&gt;remove&lt;&#x2F;code&gt;, and &lt;code&gt;get&lt;&#x2F;code&gt;. Aside from the translation to &lt;code&gt;EventKey&lt;&#x2F;code&gt;, there&#x27;s
nothing interesting going on here.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Poller {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Create a new instance of `Poller`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;crate&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            targets: Slab::new()
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Insert a new `Pollable` target into `Poller`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;crate&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;target&lt;&#x2F;span&gt;&lt;span&gt;: Pollable) -&amp;gt; EventKey {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; key = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.targets.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(target);
&lt;&#x2F;span&gt;&lt;span&gt;        EventKey(key as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Get a `Pollable` if it exists.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;crate&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;EventKey) -&amp;gt; Option&amp;lt;&amp;amp;Pollable&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.targets.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(key.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Remove an instance of `Pollable` from `Poller`.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Returns `None` if no entry was found for `key`.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;crate&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;remove&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;: EventKey) -&amp;gt; Option&amp;lt;Pollable&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.targets.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_remove&lt;&#x2F;span&gt;&lt;span&gt;(key.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And finally we&#x27;re ready to implement the most interesting part: implementing the
method to wait for events in the &lt;code&gt;Poller&lt;&#x2F;code&gt;, and map them to their respective
&lt;code&gt;EventKey&lt;&#x2F;code&gt;s. When we submit a list of &lt;code&gt;Pollable&lt;&#x2F;code&gt;s to the &lt;code&gt;poll&lt;&#x2F;code&gt; call, we get a
list of &lt;em&gt;indexes&lt;&#x2F;em&gt; back which refer to the indexes of the pollables we submitted.
These are not the same values as the &lt;code&gt;EventKey&lt;&#x2F;code&gt;s we have, so we have to
construct a lookup table to map the indexes of the pollables back to the event
keys.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Poller {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Block the current thread until a new event has triggered.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; This will clear the value of `ready_list`.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;crate&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;block_until&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Vec&amp;lt;EventKey&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; We&amp;#39;re about to wait for a number of pollables. When they wake we get
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; the *indexes* back for the pollables whose events were available - so
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; we need to be able to associate the index with the right waker.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; We start by iterating over the pollables, and keeping note of which
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; pollable belongs to which waker index
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; indexes = Vec::with_capacity(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.targets.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; targets = Vec::with_capacity(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.targets.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(index, target) in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.targets.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;            indexes.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(index);
&lt;&#x2F;span&gt;&lt;span&gt;            targets.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(target);
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Now that we have that association, we&amp;#39;re ready to poll our targets.
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; This will block until an event has completed.
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; ready_indexes = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;targets);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Once we have the indexes for which pollables are available, we need
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; to convert it back to the right keys for the wakers. Earlier we
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; established a positional index -&amp;gt; waker key relationship, so we can
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; go right ahead and perform a lookup there.
&lt;&#x2F;span&gt;&lt;span&gt;        ready_indexes
&lt;&#x2F;span&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;index&lt;&#x2F;span&gt;&lt;span&gt;| EventKey(indexes[index as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;] as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And with that, our &lt;code&gt;Pollable&lt;&#x2F;code&gt; abstraction is complete!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;designing-the-reactor-abstraction&quot;&gt;Designing the reactor abstraction&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we can track lists of pollables and a way to submit them - it&#x27;s time to
bring wakers into the mix and create a type which can be used by individual
futures to register interest in events. The WASI async runtime is fundamentally
single-threaded, so what we&#x27;ll want to use here are just the &lt;code&gt;Rc&lt;&#x2F;code&gt; and &lt;code&gt;RefCell&lt;&#x2F;code&gt;
types. We can now construct our data types; again starting with the core structures:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use super&lt;&#x2F;span&gt;&lt;span&gt;::polling::{EventKey, Poller};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::collections::HashMap;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::task::Poll;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::task::Waker;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::{cell::RefCell, rc::Rc};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;wasi::io::poll::Pollable;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Manage async system resources for WASI 0.1
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Debug, Clone)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Reactor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;inner&lt;&#x2F;span&gt;&lt;span&gt;: Rc&amp;lt;RefCell&amp;lt;InnerReactor&amp;gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The private, internal `Reactor` implementation - factored out so we can take
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; a lock of the whole.
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Debug)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;InnerReactor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;poller&lt;&#x2F;span&gt;&lt;span&gt;: Poller,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;wakers&lt;&#x2F;span&gt;&lt;span&gt;: HashMap&amp;lt;EventKey, Waker&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Reactor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Create a new instance of `Reactor`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;crate&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            inner: Rc::new(RefCell::new(InnerReactor {
&lt;&#x2F;span&gt;&lt;span&gt;                poller: Poller::new(),
&lt;&#x2F;span&gt;&lt;span&gt;                wakers: HashMap::new(),
&lt;&#x2F;span&gt;&lt;span&gt;            })),
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The reason we can get away with &lt;code&gt;Rc&amp;lt;RefCell&amp;lt;Inner&amp;gt;&amp;gt;&lt;&#x2F;code&gt; is because we control all
the accesses in the methods. We guarantee they are always short-lived and will
never overlap. Which in turn provides us with a convenient way to to be able to
call methods on &lt;code&gt;&amp;amp;self&lt;&#x2F;code&gt; rather than &lt;code&gt;&amp;amp;mut self&lt;&#x2F;code&gt;. Speaking of which, time to
implement the first method - which is a way to register interest in a &lt;code&gt;pollable&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;registering-interest-in-a-pollable&quot;&gt;Registering interest in a pollable&lt;&#x2F;h3&gt;
&lt;p&gt;This provides an async method &lt;code&gt;wait_for&lt;&#x2F;code&gt; which allows our reactor to wait
asynchronously until the call related to the &lt;code&gt;pollable&lt;&#x2F;code&gt; is ready to be
performed.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Reactor {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Wait for the pollable to resolve.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt; async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;wait_for&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;pollable&lt;&#x2F;span&gt;&lt;span&gt;: Pollable) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; pollable = Some(pollable);
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; key = None;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; This function is the core loop of our function; it will be called
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; multiple times as the future is resolving.
&lt;&#x2F;span&gt;&lt;span&gt;        future::poll_fn(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;| {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Start by taking a lock on the reactor. This is single-threaded
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; and short-lived, so it will never be contended.
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; reactor = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;borrow_mut&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Schedule interest in the `pollable` on the first iteration. On
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; every iteration, register the waker with the reactor.
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; key = key.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get_or_insert_with&lt;&#x2F;span&gt;&lt;span&gt;(|| reactor.poller.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(pollable.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;()));
&lt;&#x2F;span&gt;&lt;span&gt;            reactor.wakers.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(*key, cx.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;waker&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Check whether we&amp;#39;re ready or need to keep waiting. If we&amp;#39;re
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ready, we clean up after ourselves.
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; reactor.poller.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(key).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;ready&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;                reactor.poller.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;remove&lt;&#x2F;span&gt;&lt;span&gt;(*key);
&lt;&#x2F;span&gt;&lt;span&gt;                reactor.wakers.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;remove&lt;&#x2F;span&gt;&lt;span&gt;(key);
&lt;&#x2F;span&gt;&lt;span&gt;                Poll::Ready(())
&lt;&#x2F;span&gt;&lt;span&gt;            } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;                Poll::Pending
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        })
&lt;&#x2F;span&gt;&lt;span&gt;        .await
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What&#x27;s nice about this is that unlike other runtimes, where interest is
registered on the &lt;em&gt;object&lt;&#x2F;em&gt;, here we merely register interest on an &lt;em&gt;operation&lt;&#x2F;em&gt;.
That means that &quot;wait for this operation to be ready&quot; is a matter of calling
&lt;code&gt;reactor.wait_for(pollable).await&lt;&#x2F;code&gt;. That is significantly different than the
juggling of syscalls required in other polling models; and it means we can
encode all of the invariants necessary for the reactor directly as part of the
reactor.&lt;&#x2F;p&gt;
&lt;p&gt;In recent conversations in the Rust WG Async we&#x27;ve been discussing whether it makes sense
to have some kind of reactor hook as part of the &lt;code&gt;Context&lt;&#x2F;code&gt; in future - or
whether perhaps other mechanisms would be better. From this example I believe we
can conclude that while it might be &lt;em&gt;possible&lt;&#x2F;em&gt; to share a reactor through the
future&#x27;s context - at a high level that will always be mapped the same way to
the underlying function calls. Which at least to me puts into question whether
that is the most natural mapping.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;blocking-until-events-are-ready&quot;&gt;Blocking until events are ready&lt;&#x2F;h3&gt;
&lt;p&gt;With that out of the way, we&#x27;re ready to implement the wrapper around our
&lt;code&gt;Poller::block_until&lt;&#x2F;code&gt; call. As we implemented, it will wait for all registered
&lt;code&gt;pollers&lt;&#x2F;code&gt;, and give us back a list of &lt;code&gt;EventKey&lt;&#x2F;code&gt;s for the ones which are ready
to be woken. All we have to do is iterate over the list of keys, and call each related waker:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Block until new events are ready. Calls the respective wakers once done.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;crate&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;block_until&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; reactor = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;borrow_mut&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; key in reactor.poller.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;block_until&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; reactor.wakers.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;key) {
&lt;&#x2F;span&gt;&lt;span&gt;            Some(waker) =&amp;gt; waker.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;wake_by_ref&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;            None =&amp;gt; panic!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;tried to wake the waker for non-existent `{key:?}`&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;),
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;At first glance it might seem silly that this goes through the motions
of calling the wakers. WASI 0.2 is currently single-threaded, so by default it
will always just wake the one waker. However, it is common and encouraged to use
wakers to distinguish between events. Concurrency primitives may construct their
own wakers to keep track of identity and wake more precisely. We do not control
the wakers constructed by libraries, and it is for this reason that we have
to call all the wakers - even if by default they will do nothing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;designing-the-block-on-abstraction&quot;&gt;Designing the block_on abstraction&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we have our reactor done, we need a way to drive it. For that we&#x27;re
going to define a function &lt;code&gt;block_on&lt;&#x2F;code&gt; which takes a closure returning a future
and gives it access to the &lt;code&gt;Reactor&lt;&#x2F;code&gt;. As long as the future returned by the
closure is live, we&#x27;ll keep making progress on it - waiting on the reactor each
time the future returns &lt;code&gt;Pending&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ll be driving futures by hand here, so the first step is to define our own
instance of &lt;code&gt;Waker&lt;&#x2F;code&gt;. We&#x27;re not supporting any form of &lt;code&gt;spawn&lt;&#x2F;code&gt; function, and
instead rely on users to leverage libraries for structured concurrency, so out
of the box we can just make it a noop.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Construct a new no-op waker
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; NOTE: we can remove this once &amp;lt;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;98286&amp;gt; lands
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;noop_waker&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Waker {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VTABLE&lt;&#x2F;span&gt;&lt;span&gt;: RawWakerVTable = RawWakerVTable::new(
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Cloning just returns a new no-op raw waker
&lt;&#x2F;span&gt;&lt;span&gt;        |_| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;RAW&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `wake` does nothing
&lt;&#x2F;span&gt;&lt;span&gt;        |_| {},
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `wake_by_ref` does nothing
&lt;&#x2F;span&gt;&lt;span&gt;        |_| {},
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Dropping does nothing as we don&amp;#39;t allocate anything
&lt;&#x2F;span&gt;&lt;span&gt;        |_| {},
&lt;&#x2F;span&gt;&lt;span&gt;    );
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;RAW&lt;&#x2F;span&gt;&lt;span&gt;: RawWaker = RawWaker::new(ptr::null(), &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VTABLE&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; SAFETY: all fields are no-ops, so this is safe
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Waker::from_raw(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;RAW&lt;&#x2F;span&gt;&lt;span&gt;) }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next up is the actual &lt;code&gt;block_on&lt;&#x2F;code&gt; implementation. The core logic is basically a
&lt;code&gt;loop { match {} }&lt;&#x2F;code&gt; statement which just calls &lt;code&gt;reactor.block_until&lt;&#x2F;code&gt; on each
iteration until the future completes.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Start the event loop
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;block_on&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;F, Fut&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;: F) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Fut::&lt;&#x2F;span&gt;&lt;span&gt;Output
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    F: FnOnce(Reactor) -&amp;gt; Fut,
&lt;&#x2F;span&gt;&lt;span&gt;    Fut: Future,
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Construct the reactor
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; reactor = Reactor::new();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create the future and pin it so it can be polled
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; fut = (f)(reactor.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; fut = pin!(fut);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create a new context to be passed to the future.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; waker = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;noop_waker&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; cx = Context::from_waker(&amp;amp;waker);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Either the future completes and we return, or some IO is happening
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; and we wait.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; fut.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; cx) {
&lt;&#x2F;span&gt;&lt;span&gt;            Poll::Ready(res) =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; res,
&lt;&#x2F;span&gt;&lt;span&gt;            Poll::Pending =&amp;gt; reactor.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;block_until&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And with that, our async runtime is complete!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;using-the-async-runtime&quot;&gt;Using the async runtime&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;This section was added post-publication on 2024-03-07&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Now that we have our runtime, we can use it to wrap the calls from the &lt;code&gt;wasi&lt;&#x2F;code&gt;
library and make them async. For example, say we wanted to have a non-blocking
&lt;code&gt;sleep&lt;&#x2F;code&gt; function which waits for some &lt;code&gt;Duration&lt;&#x2F;code&gt;. We could write that by using
the
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;wasi&#x2F;0.12.1+wasi-0.2.0&#x2F;wasi&#x2F;clocks&#x2F;monotonic_clock&#x2F;fn.subscribe_duration.html&quot;&gt;&lt;code&gt;subscribe_duration&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
function and connecting it to the reactor. All we need to do is wrap it, call
it, and then wait on the pollable. That should be simple enough to do with what
we&#x27;ve written:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::time::Duration;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;wasi::time::monotonic_clock::subscribe_duration;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt; async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;sleep&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span&gt;: Duration, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;reactor&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;Reactor) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; duration = duration.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_nanos&lt;&#x2F;span&gt;&lt;span&gt;() as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;&#x2F;span&gt;&lt;span&gt;;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 1. Convert the duration to nanosecond resolution
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; pollable = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;subscribe_duration&lt;&#x2F;span&gt;&lt;span&gt;(duration);   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 2. Obtain the pollable
&lt;&#x2F;span&gt;&lt;span&gt;    reactor.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;wait_for&lt;&#x2F;span&gt;&lt;span&gt;(pollable).await;              &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 3. Wait for the pollable to be ready
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It should be simple enough to take APIs from the &lt;code&gt;wasi&lt;&#x2F;code&gt; crate, and pair them
with a call to &lt;code&gt;reactor.wait_for(..).await&lt;&#x2F;code&gt;. That&#x27;s the base pattern we&#x27;s use to
asyncify basically the entire &lt;code&gt;wasi&lt;&#x2F;code&gt; API surface.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;on-the-absence-of-a-local-executor&quot;&gt;On the absence of a local executor&lt;&#x2F;h2&gt;
&lt;p&gt;WASI 0.2 is single-threaded, and fundamentally doesn&#x27;t need access to a
&lt;code&gt;task.spawn&lt;&#x2F;code&gt; abstraction. In sync Rust we use threads to combine parallelism +
concurrency; but in async Rust we can separate the two. The
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-concurrency&#x2F;latest&#x2F;futures_concurrency&#x2F;&quot;&gt;futures-concurrency&lt;&#x2F;a&gt; library provides access to any mode of concurrency you
might want; meaning that in the absence of parallelism there is no reason for an
executor to exist.&lt;&#x2F;p&gt;
&lt;p&gt;Instead APIs such as
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-concurrency&#x2F;latest&#x2F;futures_concurrency&#x2F;future&#x2F;trait.Join.html#impl-Join-for-Vec%3CFut%3E&quot;&gt;&lt;code&gt;Vec::join&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
and
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-concurrency&#x2F;latest&#x2F;futures_concurrency&#x2F;stream&#x2F;struct.StreamGroup.html&quot;&gt;&lt;code&gt;StreamGroup&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
even provide access to the unbounded concurrency primitives people typically use
&quot;local executors&quot; for - but without any of the scoped lifetime issues plaguing
those abstractions. Here is an example of how to concurrently make two separate
HTTP requests without having to rely on &quot;local tasks&quot;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;block_on&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;reactor&lt;&#x2F;span&gt;&lt;span&gt;| async {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; client = Client::new(reactor); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; &amp;lt;- using an unpublished wrapper around `wasi::http`
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = async {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; url = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;https:&#x2F;&#x2F;example.com&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;parse&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; req = Request::new(Method::Get, url);
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = client.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(req).await;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; body = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_to_end&lt;&#x2F;span&gt;&lt;span&gt;(res).await;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; body = String::from_utf8(body).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;            println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{body}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;        };
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = async {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; url = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;https:&#x2F;&#x2F;example.com&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;parse&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; req = Request::new(Method::Get, url);
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = client.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(req).await;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; body = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_to_end&lt;&#x2F;span&gt;&lt;span&gt;(res).await;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; body = String::from_utf8(body).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;            println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{body}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;        };
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        (a, b).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;().await; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; concurrently await both `a` and `b`.
&lt;&#x2F;span&gt;&lt;span&gt;    })
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post I&#x27;ve explained WASI&#x27;s polling model and showed step-by-step how to
use it to build your own async runtime. I hope this will be useful for
maintainers of async Rust runtimes, as well as hobbyists wanting to go through
the motions of writing their own. If you prefer to just use the code I&#x27;ve shared
here today, you can do so by installing the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;wasi-async-runtime&#x2F;latest&#x2F;wasi_async_runtime&#x2F;&quot;&gt;&lt;code&gt;wasi-async-runtime&lt;&#x2F;code&gt;
crate&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Extending Rust&#x27;s Effect System</title>
            <pubDate>Fri, 09 Feb 2024 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/extending-rusts-effect-system/</link>
            <guid>https://blog.yoshuawuyts.com/extending-rusts-effect-system/</guid>
            <description>&lt;iframe class=&quot;youtube-video&quot;
src=&quot;https:&#x2F;&#x2F;www.youtube-nocookie.com&#x2F;embed&#x2F;MTnIexTt9Dk&quot;
title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay;
clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot;
allowfullscreen&gt;&lt;&#x2F;iframe&gt;
&lt;p&gt;&lt;em&gt;This is the transcript of my RustConf 2023 talk: &quot;Extending Rust&#x27;s Effect
System&quot;, presented on September 13th 2023 in Albuquerque, New Mexico and
streamed online.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;Rust has continuously evolved since version 1.0 was released in 2015. We&#x27;ve
added major features such as the try operator (&lt;code&gt;?&lt;&#x2F;code&gt;), const generics, generic
associated types (GATs), and of course: &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt;. Out of those four
features, three are what can be considered to be &quot;effects&quot;. And though we&#x27;ve
been working on them for a long time, they are all still very much in-progress.&lt;&#x2F;p&gt;
&lt;p&gt;Hello, my name is Yosh and I work as a Developer Advocate for Rust at Microsoft.
I&#x27;ve been working on Rust itself for the past five years, and I&#x27;m among other
things a member of the Rust Async WG, and the co-lead of the Rust Effects
Initiative.&lt;&#x2F;p&gt;
&lt;p&gt;The thesis of this talk is that we&#x27;ve unknowingly shipped an effect system as
part of the language in since Rust 1.0. We&#x27;ve since begun adding a number of new
effects, and in order to finish integrating them into the language we need
support for &lt;em&gt;effect generics&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In this talk I&#x27;ll explain what effects are, what makes them challenging to
integrate into the language, and how we can overcome those challenges.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rust-without-generics&quot;&gt;Rust Without Generics&lt;&#x2F;h2&gt;
&lt;p&gt;When I was new to Rust it took me a minute to figure out how to use generics. I
was used to writing JavaScript, and we don’t have generics there. So I found
myself mostly writing functions which operated on &lt;em&gt;concrete types&lt;&#x2F;em&gt;. I remember
my code felt pretty clumsy, and it wasn&#x27;t a great experience. Not compared to,
say, the code the stdlib provides.&lt;&#x2F;p&gt;
&lt;p&gt;An example of a generic stdlib function is the &lt;code&gt;io::copy&lt;&#x2F;code&gt; function. It reads
bytes from a reader, and copies them into a writer. We can give it a file, a
socket, or any combination of the two, and it will happily copy bytes from one
into the other.  This all works as long as we give it the right types.&lt;&#x2F;p&gt;
&lt;p&gt;But what if Rust actually didn&#x27;t have generics? What if the Rust I used to write
at the beginning was actually all we had? How would we write this &lt;code&gt;io::copy&lt;&#x2F;code&gt;
function? Well, given we&#x27;re trying to copy bytes between sockets and file types,
we could probably hand-code individual functions for these. For our two types
here we could write four unique functions.&lt;&#x2F;p&gt;
&lt;p&gt;But unfortunately for us that would only solve the problem right in front of us.
But the stdlib doesn’t just have two types which implement read and write. It
has 18 types which implement read, and 27 types which implement write. So if we
wanted to cover the entire API space of the stdlib, we’d need 486 functions in
total. And if that was the only way we could implement &lt;code&gt;io::copy&lt;&#x2F;code&gt;, that would
make for a pretty bad language.&lt;&#x2F;p&gt;
&lt;p&gt;Now luckily Rust does have generics, and all we ever need is the one &lt;code&gt;copy&lt;&#x2F;code&gt;
function. This means we&#x27;re free to keep adding more types into the stdlib
without having to worry about implementing more functions. We just have the one
&lt;code&gt;copy&lt;&#x2F;code&gt; function, and the compiler will take care of generating the right code
for any types we give it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-effect-generics&quot;&gt;Why effect generics?&lt;&#x2F;h2&gt;
&lt;p&gt;Types are not the only things in Rust we want to be generic over. We also have
&quot;const generics&quot; which allow functions to be generic over constant values. As
well as &quot;value generics&quot; which allow functions to be generic over different
values. This is how we can write functions which can take different values -
which is a feature present in most programming languages.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;by_value&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span&gt;: Cat) { .. }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;by_reference&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;Cat) { .. }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;by_mutable_reference&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; Cat) { .. }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But not everything that can lead to API duplication are things we can be generic
over. For example, it&#x27;s pretty common to create different methods or types
depending on whether we take a value as owned, as a reference, or as a mutable
reference. We also often create duplicate APIs for constant values and for
runtime values. As well as create duplicate structures depending on whether the
API needs to be thread-safe or not.&lt;&#x2F;p&gt;
&lt;p&gt;But out of everything which can lead to API duplication, effects are probably
one of the biggest ones. When I talk about effects in Rust, what I mean is
certain keywords such as &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; and &lt;code&gt;const&lt;&#x2F;code&gt;; but also &lt;code&gt;?&lt;&#x2F;code&gt;, and types
such as &lt;code&gt;Result&lt;&#x2F;code&gt;, and &lt;code&gt;Option&lt;&#x2F;code&gt;. All of these have a deep, semantic connection to
the language, and changes the meaning of our code in ways that other keywords
and types don&#x27;t.&lt;&#x2F;p&gt;
&lt;p&gt;Sometimes we&#x27;ll write code which doesn&#x27;t have the right effects, leading to
&lt;em&gt;effect mismatches&lt;&#x2F;em&gt;. This is also known as the &lt;em&gt;function coloring problem&lt;&#x2F;em&gt;, as
described by Robert Nystrom. Once you become aware of &lt;em&gt;effect mismatches&lt;&#x2F;em&gt; you
start seeing them all over the place, not just in Rust either.&lt;&#x2F;p&gt;
&lt;p&gt;The result of these effect mismatches is that using effects in Rust essentially
drops you into a second-rate experience. Whether you&#x27;re using const, async,
Result, or Error - almost certainly somewhere along the line you&#x27;ll run into a
compatibility issue.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; db: Option&amp;lt;Database&amp;gt; = ..;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; db = db.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;db&lt;&#x2F;span&gt;&lt;span&gt;| db.name? == &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;chashu&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Take for example the &lt;code&gt;Option::filter&lt;&#x2F;code&gt; API. It takes a type by reference and
returns a bool. If we try and use the &lt;code&gt;?&lt;&#x2F;code&gt; operator inside of it we get an error,
because the function doesn&#x27;t return &lt;code&gt;Result&lt;&#x2F;code&gt; or &lt;code&gt;Option&lt;&#x2F;code&gt;. Not being able to use
&lt;code&gt;?&lt;&#x2F;code&gt; inside of arbitrary closures is an example of an effect mismatch.&lt;&#x2F;p&gt;
&lt;p&gt;But simple functions like that only scratch the surface. Effect mismatches are
present in almost every single trait in the stdlib too. Take for example
something common like the &lt;code&gt;Debug&lt;&#x2F;code&gt; trait which is implemented on almost every
type in Rust.&lt;&#x2F;p&gt;
&lt;p&gt;We could implement the &lt;code&gt;Debug&lt;&#x2F;code&gt; trait for our made-up type &lt;code&gt;Cat&lt;&#x2F;code&gt;. The parameter
&lt;code&gt;f&lt;&#x2F;code&gt; here implements &lt;code&gt;io::Write&lt;&#x2F;code&gt; and represents a stream of bytes. And using the
&lt;code&gt;write!&lt;&#x2F;code&gt; macro we can write bytes into that stream. But if for some reason we
wanted to write bytes asynchronously into, say, an async socket. Well, we can&#x27;t
do that. &lt;code&gt;fn fmt&lt;&#x2F;code&gt; is not an async function, which means we can&#x27;t await inside of
it.&lt;&#x2F;p&gt;
&lt;p&gt;One way out of this could be to create some kind of intermediate buffer, and
synchronously write data into it. We could then write data out of that buffer
asynchronously. But that would involve extra copies we didn&#x27;t have before.&lt;&#x2F;p&gt;
&lt;p&gt;If we wanted to make it identical to what we did before, the solution would be
to create a &lt;em&gt;new&lt;&#x2F;em&gt; &lt;code&gt;AsyncDebug&lt;&#x2F;code&gt; trait which &lt;em&gt;can&lt;&#x2F;em&gt; write data asynchronously into
the stream. But we now have duplicate traits, and that&#x27;s exactly the problem
we&#x27;re trying to prevent.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s tempting to say that maybe we should just add the &lt;code&gt;AsyncDebug&lt;&#x2F;code&gt; trait and
call it a day. We can then also add async versions of &lt;code&gt;Read&lt;&#x2F;code&gt;, &lt;code&gt;Write&lt;&#x2F;code&gt;, and
&lt;code&gt;Iterator&lt;&#x2F;code&gt; too. And perhaps &lt;code&gt;Hash&lt;&#x2F;code&gt; as well, since it too writes to an output
stream. And what about &lt;code&gt;From&lt;&#x2F;code&gt; and &lt;code&gt;Into&lt;&#x2F;code&gt;? Perhaps &lt;code&gt;Fn&lt;&#x2F;code&gt;, &lt;code&gt;FnOnce&lt;&#x2F;code&gt;, &lt;code&gt;FnMut&lt;&#x2F;code&gt;, and
&lt;code&gt;Drop&lt;&#x2F;code&gt; too since they&#x27;re built-ins? And so on. The reality is that effect
mismatches are structural, and duplicating the API surface for every effect
mismatch leads to an exponential explosion of APIs. Which is similar to what
we&#x27;ve seen with data type generics earlier on.&lt;&#x2F;p&gt;
&lt;p&gt;Let me try and illustrate this for a second. Say we took the existing family of
&lt;code&gt;Fn&lt;&#x2F;code&gt; traits and introduced effectful versions of them. That is: versions which
work with &lt;code&gt;unsafe&lt;&#x2F;code&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#unsafe-note&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, &lt;code&gt;async&lt;&#x2F;code&gt;, &lt;code&gt;try&lt;&#x2F;code&gt;, &lt;code&gt;const&lt;&#x2F;code&gt;, and generators. With one effect
we&#x27;re up to six unique traits. With two effects we&#x27;re up to twelve. With all
five we&#x27;re suddenly looking at 96 different traits.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;unsafe-note&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Correction from 2024: after having discussed this with Ralf Jung
we&#x27;ve concluded that semantically &lt;code&gt;unsafe&lt;&#x2F;code&gt; in Rust is not an effect. But
syntactically it would be fair to say that &lt;code&gt;unsafe&lt;&#x2F;code&gt; is &quot;effect-like&quot;. As such
any notion of &quot;maybe-unsafe&quot; would be nonsensical. We don&#x27;t discuss such a
feature in this talk, but it is worth clearing up ahead of time in case this
leaves people wondering.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;The problem space in the stdlib is really broad. From analyzing the Rust 1.70
stdlib, by my estimate about 75% of the stdlib would interact with the const
effect. Around 65% would interact with the async effect. And around 30% would
interact with the try effect. The exact numbers are imprecise because parts of
the various effects are still in-progress. How much this will result in
practice, very much will depend on how we end up designing the language.&lt;&#x2F;p&gt;
&lt;p&gt;If you compare the numbers then it appears that close to 100% of the stdlib
would interact with one or more effect. And about 50% would interact with two or
more effects. If we consider that whenever effects interact with each other they
can lead to exponential blowup, this should warn us that clever one-off
solutions won&#x27;t cut it. I believe that the best way to deal with this is to
instead allow Rust to enable items to be generic over effects.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;stage-i-effect-generic-trait-definitions&quot;&gt;Stage I: Effect-Generic Trait Definitions&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we&#x27;ve taken a good look at what happens when we can&#x27;t be generic over
effects, it&#x27;s time we start talking about what we can do about it. The answer,
unsurprisingly, is to introduce effect generics into the language. To cover all
uses will take a few steps, so let&#x27;s start with the first, and arguably most
important one: effect-generic trait definitions.&lt;&#x2F;p&gt;
&lt;p&gt;This is important because it would allow us to introduce effectful traits as
part of the stdlib. Which would among other things would help standardize the
various async ecosystems around the stdlib.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Into&amp;lt;T&amp;gt;: Sized {     
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; T;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Into&amp;lt;Loaf&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Cat {     
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Loaf {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;nap&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s use a simple example here: the &lt;code&gt;Into&lt;&#x2F;code&gt; trait. The &lt;code&gt;Into&lt;&#x2F;code&gt; trait is used to
convert from one type into another. It is generic over a type &lt;code&gt;T&lt;&#x2F;code&gt;, and has one
function &quot;into&quot; which consumes &lt;code&gt;Self&lt;&#x2F;code&gt; and returns the type &lt;code&gt;T&lt;&#x2F;code&gt;. Say we have a
type cat which when it takes a nap turns into a cute little loaf. We can
implement &lt;code&gt;Into&amp;lt;Loaf&amp;gt;&lt;&#x2F;code&gt; for &lt;code&gt;Cat&lt;&#x2F;code&gt; by calling &lt;code&gt;self.nap&lt;&#x2F;code&gt; in the function body.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;AsyncInto&amp;lt;T&amp;gt;: Sized {     
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; T;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;AsyncInto&amp;lt;Loaf&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Cat {     
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Loaf {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;nap&lt;&#x2F;span&gt;&lt;span&gt;().await
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But what if the cat doesn&#x27;t take a nap straight away? Maybe &lt;code&gt;nap&lt;&#x2F;code&gt; should
actually be an async function. In order to &lt;code&gt;await&lt;&#x2F;code&gt; nap inside the trait impl,
the &lt;code&gt;into&lt;&#x2F;code&gt; method would need to be async. If we were writing an async trait from
scratch, we could do this by exposing a new &lt;code&gt;AsyncInto&lt;&#x2F;code&gt; trait with an async
&lt;code&gt;into&lt;&#x2F;code&gt; method.&lt;&#x2F;p&gt;
&lt;p&gt;But we don&#x27;t just want to add a new trait to the stdlib, instead we want to
&lt;em&gt;extend&lt;&#x2F;em&gt; the existing &lt;code&gt;Into&lt;&#x2F;code&gt; trait to work with the async effect. The way we
could extend the &lt;code&gt;Into&lt;&#x2F;code&gt; trait with the &lt;code&gt;async&lt;&#x2F;code&gt; effect is by making the async
effect &lt;em&gt;optional&lt;&#x2F;em&gt;. Rather than requiring that the trait is always sync or async,
implementors should be able to choose which version of the trait they want to
implement.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;maybe&lt;&#x2F;span&gt;&lt;span&gt;(async)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Into&amp;lt;Loaf&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Cat {     
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;maybe&lt;&#x2F;span&gt;&lt;span&gt;(async)]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Loaf {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;nap&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The way this would work is by adding a new notation on the trait: &quot;maybe async&quot;.
We don&#x27;t yet know what syntax we want to use for &quot;maybe async&quot;, so in this talk
we&#x27;ll be using attributes. The way the &quot;maybe async&quot; notation works is that we
mark all methods which we want to be &quot;maybe async&quot; as such. And then mark our
trait itself as &quot;maybe async&quot; too.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Into&amp;lt;Loaf&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Cat {     
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Loaf {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;nap&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;async Into&amp;lt;Loaf&amp;gt; for Cat {     
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Loaf {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;nap&lt;&#x2F;span&gt;&lt;span&gt;().await
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Implementors then get to choose whether they want to implement the sync or async
versions of the trait. And depending on which version they choose, the methods
then ends up being either sync or async. This system would be entirely
backwards-compatible, because implementing the sync version of &lt;code&gt;Into&lt;&#x2F;code&gt; would
remain the same as it is today. But people who want to implement the async
version would be able to, just by adding a few extra &lt;code&gt;async&lt;&#x2F;code&gt; keywords to the impl.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;async Into&amp;lt;Loaf&amp;gt; for Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Loaf {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;nap&lt;&#x2F;span&gt;&lt;span&gt;().await
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Into&amp;lt;Loaf, true&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;ReturnTy = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Future&amp;lt;Output = Loaf&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    fn into(self) -&amp;gt; Self::ReturnTy {
&lt;&#x2F;span&gt;&lt;span&gt;        async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;nap&lt;&#x2F;span&gt;&lt;span&gt;().await
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Under the hood the implementations desugars to regular Rust code we can already
write today. The sync implementation of the type returns a type &lt;code&gt;T&lt;&#x2F;code&gt;. But the
async impl returns an &lt;code&gt;impl Future&lt;&#x2F;code&gt; of &lt;code&gt;T&lt;&#x2F;code&gt;. Under the hood it is just a single
const bool and some associated types.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;good diagnostics&lt;&#x2F;li&gt;
&lt;li&gt;gradual stabilization,&lt;&#x2F;li&gt;
&lt;li&gt;backwards-compatibility&lt;&#x2F;li&gt;
&lt;li&gt;clear inference rules&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;It would be reasonable to ask why we&#x27;re bothering with a language feature, if
the desugaring ends up being so simple. And the reason is: effects are
everywhere, and we want to make sure effect generics feel like part of the
language. That not only means that we want to tightly control the diagnostics.
We also want to enable them to be gradually introduced, have clear language
rules, and be backwards-compatible.&lt;&#x2F;p&gt;
&lt;p&gt;But if you keep all that in mind, it&#x27;s probably okay to think of effect generics
as mostly syntactic sugar for const bools + associated types.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;stage-ii-effect-generic-bounds-impls-and-types&quot;&gt;Stage II: Effect-Generic Bounds, Impls, and Types&lt;&#x2F;h2&gt;
&lt;p&gt;Being able to declare effect-generic traits is only the beginning. The stdlib
not only exposes traits, it also exposes various types and functions. And
effect-generic traits don&#x27;t directly help with that.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;copy&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;R, W&amp;gt;(
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;reader&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; R,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;writer&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; W
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; io::Result&amp;lt;()&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    R: Read,
&lt;&#x2F;span&gt;&lt;span&gt;    W: Write;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s take our earlier &lt;code&gt;io::copy&lt;&#x2F;code&gt; example again. As we&#x27;ve said &lt;code&gt;copy&lt;&#x2F;code&gt; takes a
reader and writer, and then copies bytes from the reader to the writer. We&#x27;ve
seen this.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;async_copy&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;R, W&amp;gt;(
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;reader&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; R,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;writer&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; W
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; io::Result&amp;lt;()&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    R: AsyncRead,
&lt;&#x2F;span&gt;&lt;span&gt;    W: AsyncWrite;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now what would it look like if we tried adding an async version of this to the
stdlib today. Well, we&#x27;d need to start by giving it a different name so it
doesn&#x27;t conflict with the existing &lt;code&gt;copy&lt;&#x2F;code&gt; function. The same goes for the trait
bounds as well, so instead of taking &lt;code&gt;Read&lt;&#x2F;code&gt; and &lt;code&gt;Write&lt;&#x2F;code&gt;, this function would
take &lt;code&gt;AsyncRead&lt;&#x2F;code&gt; and `AsyncWrite.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;async_copy&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;R, W&amp;gt;(
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;reader&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; R,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;writer&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; W
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; io::Result&amp;lt;()&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    R: async Read,
&lt;&#x2F;span&gt;&lt;span&gt;    W: async Write;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now things get a little better once we have effect-generic trait definitions.
Rather than needing to take async duplicates of the &lt;code&gt;Read&lt;&#x2F;code&gt; and &lt;code&gt;Write&lt;&#x2F;code&gt; traits,
the function can instead choose the async versions of the existing &lt;code&gt;Read&lt;&#x2F;code&gt; and
&lt;code&gt;Write&lt;&#x2F;code&gt; traits. That&#x27;s already better, but it still means we have two versions
of the &lt;code&gt;copy&lt;&#x2F;code&gt; function.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;maybe&lt;&#x2F;span&gt;&lt;span&gt;(async)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;copy&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;R, W&amp;gt;(
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;reader&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; R,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;writer&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; W
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; io::Result&amp;lt;()&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    R: #[maybe(async)] Read,
&lt;&#x2F;span&gt;&lt;span&gt;    W: #[maybe(async)] Write;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Instead the ideal solution would be to allow &lt;code&gt;copy&lt;&#x2F;code&gt; itself to be generic over
the async effect, and make that determine which versions of &lt;code&gt;Read&lt;&#x2F;code&gt; and &lt;code&gt;Write&lt;&#x2F;code&gt;
we want. These are what we call &quot;effect-generic bounds&quot;. The effect of the
function and the effect of the bounds it takes all become the same. In
literature this is also known as &quot;row-polymorphism&quot;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;copy&lt;&#x2F;span&gt;&lt;span&gt;(reader, writer)?;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; infer sync
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;copy&lt;&#x2F;span&gt;&lt;span&gt;(reader, writer).await?;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; infer async
&lt;&#x2F;span&gt;&lt;span&gt;copy::&amp;lt;async&amp;gt;(reader, writer).await?; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; force async
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Because the function itself is now generic over the async effect, we need to
figure out at the call-site which variant we intended to use. This system will
make use of &lt;em&gt;inference&lt;&#x2F;em&gt; to figure it out. That&#x27;s a fancy way of saying that
the compiler is going to make an educated guess about which effects the
programmer intended to use. If they used &lt;code&gt;.await&lt;&#x2F;code&gt; they probably wanted the async
version. Otherwise they probably wanted the sync version. But as with any guess:
sometimes we guess wrong, so for that reason we want to provide an escape hatch
by enabling program authors to force the variant. We don&#x27;t know the exact syntax
for this yet, but we assume this would likely be using the turbofish notation.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;File { .. }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;File {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;P&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;: P) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;        P: AsRef&amp;lt;Path&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But effect-generics aren&#x27;t just needed for functions. If we want to make the
stdlib work well with effects, then types will need effect-generics too. This
might seem strange at first, since an &quot;async type&quot; might not be very intuitive.
But for example files on Windows need to be initialized as either sync or async.
Which means that whether they&#x27;re async or not isn&#x27;t just a property of the
functions, it&#x27;s a property of the type.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s use the stdlib&#x27;s &lt;code&gt;File&lt;&#x2F;code&gt; type as our example here. For simplicity let&#x27;s
assume it has a single method: &lt;code&gt;open&lt;&#x2F;code&gt; which returns either an error or a file.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;AsyncFile { .. }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;AsyncFile {
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;P&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;: P) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;        P: AsRef&amp;lt;AsyncPath&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we wanted to provide an async version of &lt;code&gt;File&lt;&#x2F;code&gt;, we again would need to
duplicate our interfaces. That means a new type &lt;code&gt;AsyncFile&lt;&#x2F;code&gt;, which has a new
async method &lt;code&gt;open&lt;&#x2F;code&gt;, which takes an async version of &lt;code&gt;Path&lt;&#x2F;code&gt; as an argument. And
&lt;code&gt;Path&lt;&#x2F;code&gt; needs to be async because it itself has async filesystem methods on it.
As I&#x27;ve said before: once you start looking you notice effects popping up
everywhere.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;maybe&lt;&#x2F;span&gt;&lt;span&gt;(async)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;File { .. }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;maybe&lt;&#x2F;span&gt;&lt;span&gt;(async)] 
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;File {
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;maybe&lt;&#x2F;span&gt;&lt;span&gt;(async)]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;P&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;: P) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;        P: AsRef&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span&gt;[maybe(async)] Path&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Instead of creating a second &lt;code&gt;AsyncFile&lt;&#x2F;code&gt; type, with effect generics on types
we&#x27;d be able to open &lt;code&gt;File&lt;&#x2F;code&gt; as async instead. Allowing us to keep just the one
&lt;code&gt;File&lt;&#x2F;code&gt; definition for both sync and async variants.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;maybe&lt;&#x2F;span&gt;&lt;span&gt;(async)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;copy&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;R, W&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;reader&lt;&#x2F;span&gt;&lt;span&gt;: R, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;writer&lt;&#x2F;span&gt;&lt;span&gt;: W) -&amp;gt; io::Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; buf = vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4028&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; reader.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; buf).await? {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;Ok(()),
&lt;&#x2F;span&gt;&lt;span&gt;            n =&amp;gt; writer.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write_all&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;buf[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..n]).await?,
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now I&#x27;ve sort of hand-waved away the internal implementations of both the &lt;code&gt;copy&lt;&#x2F;code&gt;
function and the &lt;code&gt;File&lt;&#x2F;code&gt; type. The way they work is a little different for the
two. In the case of the &lt;code&gt;copy&lt;&#x2F;code&gt; function, the implementation between the async
and non-async variants would be identical. If the function is compiled as async,
everything works as written. But if the function compiles as sync, then we just
remove the &lt;code&gt;.await&lt;&#x2F;code&gt;s and the function should compile as expected.&lt;&#x2F;p&gt;
&lt;p&gt;As a result of this &quot;maybe-async&quot; functions can only call sync or other
&quot;maybe-async&quot; functions. But that should be fine for most cases.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;File {
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;maybe&lt;&#x2F;span&gt;&lt;span&gt;(async)]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;P&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;: P) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;IS_ASYNC &lt;&#x2F;span&gt;&lt;span&gt;{ .. } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{ .. }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Concrete types like &lt;code&gt;File&lt;&#x2F;code&gt; are a little trickier. They often want to run
different code depending on which effects it has. Luckily types like &lt;code&gt;File&lt;&#x2F;code&gt;
already conditionally compile different code depending on the platform, so
introducing new types conditions shouldn&#x27;t be too big of a jump. The key thing
we need is a way to detect in the function body whether code is being compiled
as async or not - basically a fancy bool.&lt;&#x2F;p&gt;
&lt;p&gt;We can already do this for the const effect using the &lt;code&gt;const_eval_select&lt;&#x2F;code&gt;
intrinsic. It&#x27;s currently unstable and a little verbose, but it works reliably.
We should be able to easily adapt it to something similar for async and the rest
of the effects too.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-are-effects&quot;&gt;What are effects?&lt;&#x2F;h2&gt;
&lt;p&gt;Systems research on effects has been a topic in computer science for nearly 40
years. That&#x27;s about as old as C++. It&#x27;s become a bit of a hot topic recently in
PL spheres with research languages such as Koka, Eff, and Frank showing how
effects can be useful. And languages such as Scala, and to a lesser extent
Swift, adopting effect features.&lt;&#x2F;p&gt;
&lt;p&gt;When people talk about effects they will broadly refer to one of two things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Algebraic Effect Types:&lt;&#x2F;strong&gt; which are semantic notations on functions and contexts
that grant a permission to &lt;em&gt;do&lt;&#x2F;em&gt; something.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Algebraic Effect Handlers:&lt;&#x2F;strong&gt; which are a kind of typed control-flow
primitive which allows people to define their own versions of &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt;,
&lt;code&gt;try..catch&lt;&#x2F;code&gt;, and &lt;code&gt;yield&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A lot of languages which have effects provide both effect types and effect
handlers. These can be used together, but they are in fact distinct features. In
this talk we&#x27;ll only be discussing effect types.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt; async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;meow&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub const unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;meow&lt;&#x2F;span&gt;&lt;span&gt;() {}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What we&#x27;ve been calling &quot;effects&quot; in this talk so far have in fact been &lt;em&gt;effect
types&lt;&#x2F;em&gt;. Rust hasn&#x27;t historically called them this, and I believe that&#x27;s probably
why effect generics weren&#x27;t on our radar until recently. But it turns out that
reinterpreting some of our keywords as effect types actually makes perfect
sense, and provides us with a strong theoretical framework for how to reason
about them.&lt;&#x2F;p&gt;
&lt;p&gt;We also have &lt;code&gt;unsafe&lt;&#x2F;code&gt; which allows you to call &lt;code&gt;unsafe&lt;&#x2F;code&gt; functions. The unstable
try-block feature which doesn&#x27;t require you to &lt;code&gt;Ok&lt;&#x2F;code&gt;-wrap return types. The
unstable generator closure syntax which gives you access to the &lt;code&gt;yield&lt;&#x2F;code&gt; keyword.
And of course the &lt;code&gt;const&lt;&#x2F;code&gt; keyword which allows you evaluate code at
compile-time.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;async { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;async_fn&lt;&#x2F;span&gt;&lt;span&gt;().await }; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; async effect
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unsafe_fn&lt;&#x2F;span&gt;&lt;span&gt;() };     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; unsafe effect
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;const_fn&lt;&#x2F;span&gt;&lt;span&gt;() };       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; const effect
&lt;&#x2F;span&gt;&lt;span&gt;try { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_fn&lt;&#x2F;span&gt;&lt;span&gt;()? };          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; try effect (unstable)
&lt;&#x2F;span&gt;&lt;span&gt;|| { &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;yield&lt;&#x2F;span&gt;&lt;span&gt; my_type };       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; generator effect (unstable)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In Rust we currently have five different effects: &lt;code&gt;async&lt;&#x2F;code&gt;, &lt;code&gt;unsafe&lt;&#x2F;code&gt;, &lt;code&gt;const&lt;&#x2F;code&gt;,
&lt;code&gt;try&lt;&#x2F;code&gt;, and generators. All six of these are in various stages of completion. For
example: async Rust has functions and blocks, but no iterators or drop. Const
doesn&#x27;t have access to traits yet. Unsafe functions can&#x27;t be lowered to &lt;code&gt;Fn&lt;&#x2F;code&gt;
traits. Try does have the &lt;code&gt;?&lt;&#x2F;code&gt; operator, but try blocks are unstable. And
generators are entirely unstable; we only have the &lt;code&gt;Iterator&lt;&#x2F;code&gt; trait.&lt;&#x2F;p&gt;
&lt;p&gt;Some of these effects are what folks on the lang team have started calling
&quot;carried&quot;. Those are effects which will desugar to an actual type in the type
system. For example when you write &lt;code&gt;async fn&lt;&#x2F;code&gt;, the return type will desugar to
an &lt;code&gt;impl Future&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Some other effects are what we&#x27;re calling: &lt;em&gt;&quot;uncarried&quot;&lt;&#x2F;em&gt;. These effects don&#x27;t desugar
to any types in the type system, but serve only as a way to communicate
information back to the compiler. This is for example &lt;code&gt;const&lt;&#x2F;code&gt; or &lt;code&gt;unsafe&lt;&#x2F;code&gt;. While
we do check that the effects are used correctly, they don&#x27;t end up being lowered
to actual types.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x = try async { .. };
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;1. -&amp;gt; impl Future&amp;lt;Output = Result&amp;lt;T, E&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;2. -&amp;gt; Result&amp;lt;impl Future&amp;lt;Output = T&amp;gt;, E&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When we talk about carried effects, effect composition becomes important. Take
for example &quot;async&quot; and &quot;try&quot; together. If we have a function which has both?
What should the resulting type be? A future of Result? Or a Result containing a
Future?&lt;&#x2F;p&gt;
&lt;p&gt;Effects on functions are order-independent &lt;em&gt;sets&lt;&#x2F;em&gt;. While Rust currently does
require you declare effects in a specific order, carried effects themselves can
only be composed in one way. When we stabilized &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt;, we decided that
if an async function returned a Result, that should always return an &lt;code&gt;impl Future&lt;&#x2F;code&gt; of &lt;code&gt;Result&lt;&#x2F;code&gt;.  And because effects are &lt;em&gt;sets&lt;&#x2F;em&gt; and not dependent on
ordering, we can define the way carried effects should compose as part of the
language.&lt;&#x2F;p&gt;
&lt;p&gt;People can still opt-out from the built-in composition rules by manually writing
function signatures. But this is rare, and for the overwhelming majority of uses
the built-in composition rules will be the right choice.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;meow&lt;&#x2F;span&gt;&lt;span&gt;() {}  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; maybe-const
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span&gt;{}            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; always-const
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;const&lt;&#x2F;code&gt; effect is a bit different from the other effects. &lt;code&gt;const&lt;&#x2F;code&gt; blocks are
&lt;em&gt;always&lt;&#x2F;em&gt; evaluated during compilation. While &lt;code&gt;const&lt;&#x2F;code&gt; functions merely &lt;em&gt;can&lt;&#x2F;em&gt; be
evaluated during during compilation. It&#x27;s perfectly fine to call them at runtime
too. This means that when we write &lt;code&gt;const fn&lt;&#x2F;code&gt;, we&#x27;re already writing
effect-generics. This mechanism is the reason why we&#x27;ve gradually been able to
introduce const into the stdlib in a backwards-compatible way.&lt;&#x2F;p&gt;
&lt;p&gt;Const is also a bit strange in that among other things it disallows access to
the host runtime, it can&#x27;t allocate, and it can&#x27;t access globals. This feels
different from effects like say, &lt;code&gt;async&lt;&#x2F;code&gt;, which only allow you to do more
things.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;effect set&lt;&#x2F;th&gt;&lt;th&gt;can access&lt;&#x2F;th&gt;&lt;th&gt;cannot access&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;std rust&lt;&#x2F;td&gt;&lt;td&gt;non-termination, unwinding, non-determinism, statics, runtime heap, host APIs&lt;&#x2F;td&gt;&lt;td&gt;N&#x2F;A&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;alloc&lt;&#x2F;td&gt;&lt;td&gt;non-termination, unwinding, non-determinism, globals, runtime heap&lt;&#x2F;td&gt;&lt;td&gt;host APIs&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;core&lt;&#x2F;td&gt;&lt;td&gt;non-termination, unwinding, non-determinism, globals&lt;&#x2F;td&gt;&lt;td&gt;runtime heap, host APIs&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;const&lt;&#x2F;td&gt;&lt;td&gt;non-termination, unwinding&lt;&#x2F;td&gt;&lt;td&gt;non-determinism, globals, runtime heap, host APIs&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;What&#x27;s missing from this picture is that all functions in Rust carry an implicit
set of effects. Including some effects we can&#x27;t directly name yet. When we write
&lt;code&gt;const&lt;&#x2F;code&gt; functions, our functions have a different set of effects, than if we
write &lt;code&gt;no_std&lt;&#x2F;code&gt; functions, which again are different from regular &quot;std&quot; rust
functions.&lt;&#x2F;p&gt;
&lt;p&gt;The right way of thinking about const, std, etc. is as adding a different
effects to the empty set of effects. If we start from zero, then all effects are
merely additive. They just add up to different numbers.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately in Rust we can&#x27;t yet name the empty set of effects. In effect
theory this is called the &quot;total effect&quot;. And some languages such as Koka do
support the &quot;total&quot; effect. In fact, Koka&#x27;s lead developer has estimated that
around 70% of a typical Koka program can be total. Which begs the question: if
we could express the total effect in Rust, could we see similar numbers?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;stage-iii-more-effects&quot;&gt;Stage III: More Effects&lt;&#x2F;h2&gt;
&lt;p&gt;So far we&#x27;ve only talked about how we could finish the work on existing effects
such as &lt;code&gt;const&lt;&#x2F;code&gt; and &lt;code&gt;async&lt;&#x2F;code&gt;. But one nice thing of effect generics is that they
would not only allow us to finish our ongoing effects work. It would also lower
the cost of introducing &lt;em&gt;new&lt;&#x2F;em&gt; effects to the language.&lt;&#x2F;p&gt;
&lt;p&gt;Which opens up the question: if we could add more effects, which effects might
make sense to add? The obvious ones would be to actually finish adding &lt;code&gt;try&lt;&#x2F;code&gt; and
generator functions. But beyond that, there are some interesting effects we
could explore. For brevity I&#x27;ll only discuss what these features are, and not
show code examples.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;no-divergence&lt;&#x2F;strong&gt;: guarantees that a function cannot loop indefinitely,
opening up the ability to perform static runtime-cost analysis.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;no-panic&lt;&#x2F;strong&gt;: guarantees a function will never produce a panic, causing
the function to unwind.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;parametricity&lt;&#x2F;strong&gt;: guarantees that a function only operates on its arguments. That
means no implicit access to statics, no global filesystem, no thread-locals.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;capability-safety&lt;&#x2F;strong&gt;: guarantees that a function is not only parametric, but can&#x27;t
downcast abstract types either. Say if you get an &lt;code&gt;impl Read&lt;&#x2F;code&gt;, you can&#x27;t reverse
it to obtain a &lt;code&gt;File&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;destructor linearity&lt;&#x2F;strong&gt;: guarantees that &lt;code&gt;Drop&lt;&#x2F;code&gt; will &lt;em&gt;always&lt;&#x2F;em&gt; be called,
making it a safety guarantee.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;pattern types&lt;&#x2F;strong&gt;: enables functions to operate directly on variants of enums
and numbers&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;must-not-move types&lt;&#x2F;strong&gt;: would be a generalization of pinning and the
pin-project system, making it a first-class language feature&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Though there&#x27;s nothing inherently stopping us from adding any of these features
into Rust today, in order to integrate them into the stdlib without breaking
backwards-compatibility we need effect generics first.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;effect &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const  &lt;&#x2F;span&gt;&lt;span&gt;= diverge + panic;
&lt;&#x2F;span&gt;&lt;span&gt;effect core   = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span&gt;+ statics + non_determinism;
&lt;&#x2F;span&gt;&lt;span&gt;effect alloc  = core + heap;
&lt;&#x2F;span&gt;&lt;span&gt;effect std    = alloc + host_apis;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This brings us to the final part of the design space: effect aliases. If we keep
adding effects it&#x27;s very easy to eventually reach into a situation where we have
our own version of &quot;public static void main&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;In order to mitigate that it would instead be great if we could name specific
sets of effects. In a way we&#x27;ve already done that, where &lt;code&gt;const&lt;&#x2F;code&gt; represents &quot;may
loop forever&quot; and &quot;may panic&quot;. If we actually had &quot;may loop forever&quot; and &quot;may
panic&quot; as built-in effects, then we could redefine &lt;code&gt;const&lt;&#x2F;code&gt; as an alias to those.&lt;&#x2F;p&gt;
&lt;p&gt;Fundamentally this doesn&#x27;t change anything we&#x27;ve talked about so far. It&#x27;s just
that this would syntactically be a lot more pleasant to work with. So if we ever
reach a state where we have effect generics and we want notice we maybe have one
too many notation in front of our functions, it may be time for us to start
looking into this more seriously.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;outro&quot;&gt;Outro&lt;&#x2F;h2&gt;
&lt;p&gt;Rust already includes effect types such as async, const, try, and unsafe.
Because we can&#x27;t be generic over effect types yet, we usually have to choose
between either duplicating code, or just not addressing the use case. And this
makes for a language which feels incredibly rough once you start using effects.
Effect generics provide us with a way to be generic over effects, and we&#x27;ve
shown they can be implemented today as mostly as syntax sugar over
const-generics.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;re currently in the process of formalizing the effect generic work via the
A-Mir-Formality. MIR Formality is an in-progress formal model of Rust&#x27;s type
system. Because effect generics are relatively straight forward but have
far-reaching consequences for the type system, it is an ideal candidate to test
as part of the formal model.&lt;&#x2F;p&gt;
&lt;p&gt;In parallel the const WG has also begun refactoring the way const functions are
checked in the compiler. In the past const-checking happened right before borrow
checking at the MIR level. In the new system const-checking will happen much
sooner, at the HIR level. This will not only make the code more maintainable, it
will also be generalizable to more effects if needed.&lt;&#x2F;p&gt;
&lt;p&gt;Once both the formal modeling and compiler refactorings conclude, we&#x27;ll begin
drafting an RFC for effect-generic trait definitions. We expect this to happen
sometime in 2024.&lt;&#x2F;p&gt;
&lt;p&gt;And that&#x27;s the end of this talk. Thank you so much for being with me all the way
to the end. None of the work in this talk would have been possible without the
following people:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Oliver Scherer (AWS)&lt;&#x2F;li&gt;
&lt;li&gt;Eric Holk (Microsoft)&lt;&#x2F;li&gt;
&lt;li&gt;Niko Matsakis (AWS)&lt;&#x2F;li&gt;
&lt;li&gt;Daan Leijen (Microsoft)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Thank you!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Will it block?</title>
            <pubDate>Wed, 07 Feb 2024 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/what-is-blocking/</link>
            <guid>https://blog.yoshuawuyts.com/what-is-blocking/</guid>
            <description>&lt;p&gt;Will this function block?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;work&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;y&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    x + y
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;How about this function?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;work&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; prev = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; curr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;_ in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..x {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; next = prev + curr;
&lt;&#x2F;span&gt;&lt;span&gt;        prev = curr;
&lt;&#x2F;span&gt;&lt;span&gt;        curr = next;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    curr
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or this one?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;sha256::digest;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;work&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;input&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; String {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;digest&lt;&#x2F;span&gt;&lt;span&gt;(input)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Will this function block?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::{thread, time::Duration};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;work&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    thread::sleep(Duration::from_nanos(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Perhaps this one will?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::{thread, time::Duration};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;work&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    thread::sleep(Duration::from_millis(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or how about this one, does this block?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::{thread, time::Duration};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;work&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    thread::sleep(Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s try another; does this block?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::{thread, time::Duration};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;work&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    thread::spawn(|| {}).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Up next: does this block?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::{thread, time::Duration};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;work&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;meow&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Last one; does this block?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::fs::File;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::io::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::os::unix::io::FromRawFd;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;work&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; f = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ File::from_raw_fd(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;) };
&lt;&#x2F;span&gt;&lt;span&gt;    write!(&amp;amp;mut f, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;meow&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And so on.&lt;&#x2F;p&gt;
&lt;p&gt;Determining whether something &quot;is blocking&quot; is a messy endeavor because
computers are messy. Whether something blocks is not something we can
objectively determine, but depends on our own definitions and uses. A system
call which resolves quickly might not be considered &quot;blocking&quot; at all
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#read-speeds&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, while a computation which takes a long time might be. The Tokio
folks wrote the following about it &lt;a href=&quot;https:&#x2F;&#x2F;tokio.rs&#x2F;blog&#x2F;2020-04-preemption&quot;&gt;a few years
ago&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;read-speeds&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Modern storage and networking devices can get pretty darn fast.
A modern PCIe connection can transfer 128GB&#x2F;s or 1Tb&#x2F;s. Sub-millisecond response
times for storage are not unheard of either. And even network calls, for example
between processes (containers) or between machines in a data center, can resolve
incredibly quickly.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;blockquote&gt;
&lt;p&gt;[…] it is very hard to define &quot;progress&quot;. A naive definition of progress is
whether or not a task has been scheduled for over some unit of time. For
example, if a worker has been stuck scheduling the same task for more than
100ms, then that worker is flagged as blocked and a new thread is spawned. In
this definition, how does one detect scenarios where spawning a new thread
reduces throughput? This can happen when the scheduler is generally under load
and adding threads would make the situation much worse.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Even if we decide something is &quot;blocking&quot; after an arbitrary cutoff - that might
still not do us any good if the overall throughput of the system is reduced.
Determining whether something is objectively blocking or not might be the most useful
question to be asking. Alice Ryhl (also of Tokio) had the following &lt;a href=&quot;https:&#x2F;&#x2F;ryhl.io&#x2F;blog&#x2F;async-what-is-blocking&#x2F;&quot;&gt;to
say&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;In case you forgot, here&#x27;s the main thing you need to remember:
Async code should never spend a long time without reaching an &lt;code&gt;.await&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I believe this is a much more useful framing. Rather than attempting (and
failing) to categorize calls as &quot;blocking&quot;, we should identify where we&#x27;re
spending longer stretches of time without yielding back to the runtime - and
ensure we can correct it when we don&#x27;t. In async-std I introduced the
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;latest&#x2F;async_std&#x2F;task&#x2F;fn.yield_now.html&quot;&gt;&lt;code&gt;task::yield_now&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
function to help with this &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#post&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Tokio subsequently &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio&#x2F;latest&#x2F;tokio&#x2F;task&#x2F;fn.yield_now.html&quot;&gt;adopted
it&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#new-tokio&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, and
for WASI&#x27;s async model a similar function is being considered too.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;post&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;The original issue where I introduced this idea is &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;async-rs&#x2F;async-std&#x2F;issues&#x2F;290&quot;&gt;still
available&lt;&#x2F;a&gt; in case anyone is
reading about the motivation for this at the time. We very clearly modeled it
after &lt;code&gt;thread::yield_now&lt;&#x2F;code&gt;, but async.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;new-tokio&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;I believe they&#x27;ve been working on an alternative system to this
for a few years now, but I&#x27;m not sure what the state of that is.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;The goal of this post is to show by example the ambiguity present when
attempting to create an objective classification of which code counts as
&quot;blocking&quot;. As well as taking the opportunity to highlight previous writing on
the topic.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Special thanks to &lt;a href=&quot;https:&#x2F;&#x2F;www.red-bean.com&#x2F;jimb&#x2F;&quot;&gt;Jim Blandy&lt;&#x2F;a&gt;, who during my
review of &lt;a href=&quot;https:&#x2F;&#x2F;www.oreilly.com&#x2F;library&#x2F;view&#x2F;programming-rust-2nd&#x2F;9781492052586&#x2F;&quot;&gt;The Crab
Book&lt;&#x2F;a&gt;
convinced me it is actually fine to use a synchronous mutex in asynchronous
code, in turn pointing me towards &lt;a href=&quot;https:&#x2F;&#x2F;ryhl.io&#x2F;blog&#x2F;async-what-is-blocking&#x2F;&quot;&gt;Alice&#x27;s writing&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Reframing WIT as primarily a machine format</title>
            <pubDate>Sun, 19 Nov 2023 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/rethinking-wit-as-a-machine-format/</link>
            <guid>https://blog.yoshuawuyts.com/rethinking-wit-as-a-machine-format/</guid>
            <description>&lt;p&gt;&lt;em&gt;This is a &quot;short&quot; post. Unlike my usual (lengthy) research pieces, this is
mostly a train-of-thought, low-edit post intended to convey an idea or
perspective I thought would be useful to write down.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;edit(2023-11-19):&lt;&#x2F;strong&gt; &lt;em&gt;I&#x27;ve changed the title of this post from &quot;Rethinking WIT&quot;
to &quot;Reframing WIT&quot;. I strongly hold that WIT being human-readable is a good
thing we shouldn&#x27;t change, even though in this post I make the case that despite
that it probably shouldn&#x27;t be the primary way we interact with it.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Earlier this year I wrote about how I believe &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;compiled-html&#x2F;&quot;&gt;HTML is too complex to be
feasibly written by hand&lt;&#x2F;a&gt;, and
rather than linting manually authored HTML for errors it&#x27;s probably more
effective to treat HTML as a target which should be compiled to. I ended up
putting these ideas to practice in the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;html&#x2F;latest&#x2F;html&#x2F;&quot;&gt;html crate for
Rust&lt;&#x2F;a&gt;, and I think that ended up being
roughly the right idea. At the core of this was a reframing of &quot;HTML&quot; as this
thing that&#x27;s meant to be read and written by humans, to a format that is
primarily intended to be produced and ingested by machines.&lt;&#x2F;p&gt;
&lt;p&gt;Recently I&#x27;ve been using WIT - the IDL format used to define Wasm
Components with - and I&#x27;m slowly starting to form opinions about it. Yesterday I
wrote about why I believe ABIs can be described as: &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;reasoning-about-abis&#x2F;&quot;&gt;&quot;A type system + object
encoding + calling
convention&quot;&lt;&#x2F;a&gt;. But today I
want to take a slightly different perspective on WIT and share an opinion I&#x27;ve
started forming: I believe that WIT should primarily be produced and consumed by
tools, and not by humans. This is a departure from how people have been
reasoning about WIT so far - which is to think of WIT as a human-readable format
people will want to read and write by hand. In this post I want to explain why I
believe this is probably a better way to reason about WIT.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;interacting-with-wit&quot;&gt;Interacting with WIT&lt;&#x2F;h2&gt;
&lt;p&gt;I believe that from a programmer&#x27;s perspective all WIT usage can be roughly
broken up into two categories: consuming WIT definitions to use in programs. And
producing WIT definitions to be used in other programs, or to run your program
in a certain runtime. I believe that when we &lt;em&gt;import&lt;&#x2F;em&gt; WIT, we probably don&#x27;t
want to read WIT files directly. What we&#x27;re more likely interested in are the
bindings which would be generated for our programming language. Or perhaps if
we&#x27;re familiar with WIT itself, we might be interested in an interactive doc
explorer a la &lt;code&gt;rustdoc&lt;&#x2F;code&gt; to navigate the type hierarchy.&lt;&#x2F;p&gt;
&lt;p&gt;If we&#x27;re going to be exporting code using WIT, then we probably want to start by
writing the code itself. In Rust when we want to serialize types we don&#x27;t
typically start writing a &lt;a href=&quot;https:&#x2F;&#x2F;json-schema.org&quot;&gt;JSON Schema&lt;&#x2F;a&gt; - instead we
start by writing our structs and adding a &lt;a href=&quot;https:&#x2F;&#x2F;serde.rs&#x2F;derive.html&quot;&gt;serde
derive&lt;&#x2F;a&gt; at the top. And we don&#x27;t just do this for JSON, we take a &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;structopt&#x2F;latest&#x2F;structopt&#x2F;&quot;&gt;similar
data-first approach&lt;&#x2F;a&gt; for command
lines too. I believe Wasm Components and their WIT definitions would likely do
well with a similar approach. Because integrating it into the language like this
is by far the path of least resistance.&lt;&#x2F;p&gt;
&lt;p&gt;I believe this will probably hold true for the majority of programmers. Rather
than writing or consuming types authored in WIT, it&#x27;ll be much easier to reason
about components in terms of how they integrate into the language. And if for
some reason reasoning about the bindings is not sufficient, a documentation tool
will probably be the easier to way to explore WIT APIs directly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-perspectives-may-differ&quot;&gt;Why perspectives may differ&lt;&#x2F;h2&gt;
&lt;p&gt;WASI Preview 2 hasn&#x27;t been released yet, and so up until this point the majority
of people working with WIT haven&#x27;t actually been programmers trying to build
things &lt;em&gt;with&lt;&#x2F;em&gt; WIT. So far the people using WIT have mostly been the people
working on WASI itself, primarily working to define the language-agnostic
interfaces everyone will be writing their programs against.&lt;&#x2F;p&gt;
&lt;p&gt;And so I think this is a likely explainer for why the readability of WIT has
been highly valued so far. The work the majority of people using WIT today is to
write WIT by hand.  But I believe that once Preview 2 releases, this will likely
become a minority use case. If done right, most people working with WIT will be
using it via programming languages instead.&lt;&#x2F;p&gt;
&lt;p&gt;Even for system rewrites I believe it&#x27;s likely easiest to generate bindings for
an existing impl directly from a language. Then take the WIT definitions
generated by that, and use that as the interface for the new implementation. At
no point does this require people to directly interact with WIT definitions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;on-tradeoffs&quot;&gt;On tradeoffs&lt;&#x2F;h2&gt;
&lt;p&gt;To me it makes sense that if we believe that the primary way people use WIT is
either write it by hand, or read the source files, that the property of
&quot;readability&quot; is one we&#x27;re least keen to compromise on. I&#x27;m not quite sure about
the exact tradeoffs; but my understanding is that the &quot;readability&quot; of WIT has
been fairly important.&lt;&#x2F;p&gt;
&lt;p&gt;So far I&#x27;ve been making the case that I believe people are more likely to be
ingesting WIT using language-specific bindings, producing it via language
ascriptions, and reading it via documentation tools. And so if that&#x27;s the case,
then &quot;readability&quot; may perhaps be something we&#x27;re more willing to compromise on
in favor of other properties.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s not that I&#x27;m trying to argue that being able to write WIT by hand
or read it directly isn&#x27;t important. What I&#x27;m trying to say is that I don&#x27;t
believe it necessarily is the &lt;em&gt;most&lt;&#x2F;em&gt; important property.  There may be other
properties, like expressivity or machine-parsability, which would compromise
readability. If we value &quot;readability&quot; differently, then we may very well end up
making different decisions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;where-to-go-from-here&quot;&gt;Where to go from here?&lt;&#x2F;h2&gt;
&lt;p&gt;I believe that the more closely we can integrate Wasm Components&#x2F;WASI with
language toolchains and guest languages, the easier it will be for people to
adopt it. The explainer I&#x27;ve used for this in the past is in terms of &quot;deltas&quot;.
The less people need to deviate from their existing workflows to do a new thing,
the more likely it is they&#x27;ll want to try the new thing. Applied to Components: the
more it feels like importing and exporting Components is like using any other
types in that language, the more likely it is that people are willing to use it.&lt;&#x2F;p&gt;
&lt;p&gt;With that in mind, I would like us to start thinking about ways in which we can
remove manually authored WIT entirely from the end-to-end experience. If done
right, both importing and exporting WIT definitions from guest languages should
feel completely native. As if we were importing or exporting any other
library written in that same language. I feel like we&#x27;re close to that for some
languages &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#impressive&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, but I believe we can probably improve on it.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;impressive&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;I want to add here: the existing efforts I&#x27;ve seen on this front
are really impressive! I&#x27;m in no way trying to snub the existing work done!&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;The other thing I think we should explore is a native &lt;code&gt;wit-doc&lt;&#x2F;code&gt; tool which can
be used to render WIT definitions to HTML. My thinking is that this should be
modeled loosely after rustdoc or Swift&#x27;s DocC. Given plans are plans to make
progress on the Warg registry next year - this seems like something which could
integrate nicely with that too. Over in Rust land, one of my least favorite
splits is between &quot;docs.rs&quot; and &quot;cargo.io&quot; - in my opinion it would make sense
to merge these two. And given &lt;a href=&quot;https:&#x2F;&#x2F;bytecodealliance.github.io&#x2F;wit-bindgen&#x2F;&quot;&gt;wit-bindgen already runs in the
browser&lt;&#x2F;a&gt;, we could probably
also generate previews of what generated output bindings for various programming
languages would look like. Not unlike the SDK example generators used in some of
the world&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;stripe.com&#x2F;docs&#x2F;api?lang=curl&quot;&gt;fanciest docs&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this (short) post I&#x27;ve tried to make the case that while historically WIT has
been authored by hand and read from source files, that may not necessarily be
continue being true in the future. To me it seems more likely that once Preview
2 is released, people using Wasm Components will primarily be interested in
using Wasm Components directly from source languages. Since that is the path of
least friction. And in the case people need to look up WIT APIs directly, a
(hosted) documentation tool will probably provide a better experience than
reading files directly from source.&lt;&#x2F;p&gt;
&lt;p&gt;I argue that if we no longer believe that people will primarily interact with
WIT by manually authoring WIT files, and reading them from source, that the
&quot;readability&quot; property of the WIT format may become less important. That&#x27;s not
to say it should ever be deemed unimportant, since there are valid reasons to
interact directly with WIT files. But it may be the case that if change how we
value this property, we will become more willing to trade it off in favor of
other properties.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Reasoning about ABIs</title>
            <pubDate>Sat, 18 Nov 2023 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/reasoning-about-abis/</link>
            <guid>https://blog.yoshuawuyts.com/reasoning-about-abis/</guid>
            <description>&lt;p&gt;&lt;em&gt;Note: this post is not my usual research posts; but more a loose collection of
thoughts I&#x27;ve been thinking of recently. I might start tagging these as &quot;short&quot;,
since I&#x27;m writing and publishing before fully validating.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Not long after I started programming I developed an intuition for what APIs are:
they are the interfaces we use in our applications to communicate between
distinct components. But there was this other term, &quot;ABI&quot;, which I didn&#x27;t quite
understand. &quot;Application Binary Interface&quot; is not very descriptive if you
haven&#x27;t used it before. Does it mean &quot;binary&quot; because it&#x27;s encoded? But APIs use
encodings too. If an ABI is separate from an API, are we not supposed to program
against ABIs? What are the differences?&lt;&#x2F;p&gt;
&lt;p&gt;Over the past few months I&#x27;ve been helping out with getting WASI Preview 2 over
the finish line&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#eta&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Part of WASI Preview 2 are Wasm Components and WIT
definitions, which both are part of an overarching system called &quot;The
Component Model&quot;. In broad terms, Components in Wasm are able to communicate
with one another via a stable ABI encoding, which is accompanied by WIT (an
Interface Definition Language) that can be used to describe system interfaces.
For example like so:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;eta&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;ETA for WASI Preview 2 at the time of writing: either December this year or
January next year; it&#x27;s November now.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;wit&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-wit &quot;&gt;&lt;code class=&quot;language-wit&quot; data-lang=&quot;wit&quot;&gt;&lt;span&gt;package example:cat;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;interface cat {
&lt;&#x2F;span&gt;&lt;span&gt;  meow: func() -&amp;gt; string;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;world cats {
&lt;&#x2F;span&gt;&lt;span&gt;  export cat;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This defines a package &lt;code&gt;cat&lt;&#x2F;code&gt; in the namespace &lt;code&gt;example&lt;&#x2F;code&gt;, providing a set of
export &lt;code&gt;cats&lt;&#x2F;code&gt;, which includes the &lt;code&gt;cat&lt;&#x2F;code&gt; interface. In the component model we
know how to take this interface, and encode this as a Wasm Component. Which can
then be imported directly by other components, and have bindings generated for
it for any language via
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytecodealliance&#x2F;wit-bindgen&quot;&gt;&lt;code&gt;wit-bindgen&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. WASI
(WebAssembly System&#x2F;Standard Interfaces) are all defined in terms of WIT, and
describe standard ways of interfacing with things like system clocks,
filesystems, networks, and in the future caches and queues too.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m really used to thinking of ABIs in terms of data encodings and byte
offsets. In Rust we can slap &lt;code&gt;pub extern &quot;C&quot;&lt;&#x2F;code&gt; on any type to change the way it&#x27;s
laid out in memory. But it has limitations; like for example it doesn&#x27;t know
what to do with &lt;code&gt;async fn&lt;&#x2F;code&gt;.  In the past I&#x27;ve also worked with other IDL formats
such as &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Web_IDL&quot;&gt;WebIDL&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Component_Object_Model&quot;&gt;COM&lt;&#x2F;a&gt;, and
&lt;a href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;uwp&#x2F;winrt-cref&#x2F;winmd-files&quot;&gt;WinMD&lt;&#x2F;a&gt;. And while
all of these have helped me understood what an ABI &lt;em&gt;does&lt;&#x2F;em&gt;, they haven&#x27;t really
helped me understand what an ABI fundamentally &lt;em&gt;is&lt;&#x2F;em&gt;. But now that I&#x27;ve worked
with WIT, I now believe that the better way to think of ABIs as just a different
application of type systems:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Application Binary Interface&lt;&#x2F;strong&gt;: A type system with a specified serialization
format and calling convention &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#calling-convention&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Programming Language&lt;&#x2F;strong&gt;: A type system with runtime behavior (&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Operational_semantics&quot;&gt;operational
semantics&lt;&#x2F;a&gt;).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;calling-convention&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;A &quot;calling convention&quot; determines the way functions are
invoked; how arguments are mapped to registers, etc.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;The Wasm Component model doesn&#x27;t just define types like &quot;string&quot; or &quot;record&quot;,
it also has a (limited &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#limited&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;) notion of generic types too. For example &lt;code&gt;result&lt;&#x2F;code&gt; and
&lt;code&gt;option&lt;&#x2F;code&gt; are generic types, so you can define functions which return a
&lt;code&gt;result&amp;lt;string, error&amp;gt;&lt;&#x2F;code&gt; to indicate they&#x27;re fallible. I never considered that
ABIs could contain ADTs &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#adt&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, but WIT clearly has it. Which to me signals that (with
some constraints), we can apply the wealth of type system theory we&#x27;ve built up
over the years to ABIs as well.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;limited&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;There are currently four built-in generics in WIT. It&#x27;s unclear
whether it&#x27;ll support user-defined generics in the future since that would
complicate implementations. I&#x27;d love to see it though.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;adt&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;&quot;Algebraic Data Type&quot; - which are types which can carry data. These
include both enums (sum types) and structs (product types) in Rust. What&#x27;s cool
about them is that they&#x27;re compositional because an ADT can carry more ADTs.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;The boundaries between ABIs and programming languages in practice can often get
murky though. As we&#x27;ve seen with &lt;code&gt;extern &quot;C&quot;&lt;&#x2F;code&gt; in Rust, programming languages can
define ABIs internally as well. And vice versa: some ABIs may depend on runtime
semantics of a language too. But in its broadest terms: I believe an ABI &lt;em&gt;must&lt;&#x2F;em&gt;
define a data encoding, but doesn&#x27;t need to define runtime semantics. And a
programming language &lt;em&gt;must&lt;&#x2F;em&gt; define operational semantics, but doesn&#x27;t have to
define an encoding &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#internal&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. And I feel like that provides a much crisper way
to think about what ABIs actually are, rather than just what they&#x27;re used for?&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;internal&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;A data encoding is still necessary to actually encode instructions
on a machine; but that doesn&#x27;t need to be part of the programming language - it
can be an implementation of the compiler. And multiple compilers for the same
language can truthfully compile the same language, despite not needing to agree
on the encoding. As long as the operational semantics end up working as specified.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;two-kinds-of-abis-added-2023-11-18&quot;&gt;Two Kinds of ABIs (added 2023-11-18)&lt;&#x2F;h2&gt;
&lt;p&gt;I think it&#x27;s fair to say there are two ways to think about ABIs. One is just as
the low-level encoding of types + calling conventions. The WASI Component model
has a document dedicated to what is called &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;component-model&#x2F;blob&#x2F;main&#x2F;design&#x2F;mvp&#x2F;CanonicalABI.md&quot;&gt;&quot;the canonical
ABI&quot;&lt;&#x2F;a&gt;
which only specifies the encoding and calling conventions.&lt;&#x2F;p&gt;
&lt;p&gt;The way I&#x27;m talking about ABIs here in this post is one step above that, where
we not only consider the WASI canonical ABI, but also the WIT IDL format as a
part of &quot;ABI&quot;. Both are designed with each other in mind, and having WIT without
the canonical ABI doesn&#x27;t make much sense. This feels very similar to my
experience working on &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;microsoft&#x2F;windows-rs&quot;&gt;windows-rs&lt;&#x2F;a&gt;,
which ingests WinMD definitions and knows how to project those into the WinRT
calling convention. Maybe it makes sense to just have ABIs refer to the
low-level calling convention, and have a different name for the IDL + ABI
system? But given how tightly these are linked, I&#x27;m not sure it&#x27;s worth
distinguishing between the two? Or whether talking about it in terms of like:
&quot;ABI encoding&quot; and &quot;ABI description&quot; are enough? If anyone knows of better
terminology for this, I&#x27;d love to hear it!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-abis-require-a-type-system-added-2023-11-18&quot;&gt;Why ABIs require a type system (added 2023-11-18)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;hachyderm.io&#x2F;@thejpster&quot;&gt;Jonathan Pallant&lt;&#x2F;a&gt; asked some really good
questions on Mastodon about whether high-level IDLs such as WIT can conceptually
be separated from the underlying encoding. From their perspective as an embedded
systems engineer, ABIs are about object encodings + calling conventions. Since
from their perspective it was primarily about encodings, the need for a
higher-level IDL or a type system didn&#x27;t really make sense. Which is a really
fair perspective, and it made me scratch my head a little. But I think I&#x27;ve
found an explanation for why the two can&#x27;t be separated.&lt;&#x2F;p&gt;
&lt;p&gt;Take for example C. There is the programming language &quot;C&quot;, and then there are
separate calling conventions. For example on POSIX x86-64 platforms it uses the
&quot;x86-64 System V&quot; calling convention. On 32-bit POSIX it uses the 32-bit &quot;System
V&quot; calling convention. Gankra has written a great post about &lt;a href=&quot;https:&#x2F;&#x2F;faultlore.com&#x2F;blah&#x2F;c-isnt-a-language&#x2F;&quot;&gt;the C language and
the importance of ABIs&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I believe that when we talk about &quot;C ABIs&quot; (plural as there is no canonical
ABI), it&#x27;s not enough to just point at the encoding and calling conventions. As
Gankra covered in her post; it&#x27;s also important that there is a shared
understanding of types. You can&#x27;t implement the &quot;C ABI&quot; if you don&#x27;t also encode
what an &lt;code&gt;int&lt;&#x2F;code&gt; in C is. If &lt;code&gt;intmax_t&lt;&#x2F;code&gt; was not part of the &quot;C ABI&quot;, then it would
not be an issue to change it either.&lt;&#x2F;p&gt;
&lt;p&gt;Taking this back to Wasm Components: while there is something called the
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;component-model&#x2F;blob&#x2F;main&#x2F;design&#x2F;mvp&#x2F;CanonicalABI.md&quot;&gt;&quot;Canonical
ABI&quot;&lt;&#x2F;a&gt;
which defines the encoding of Wasm Components. If anything wants to implement
the &quot;Wasm Component ABI&quot;, they can&#x27;t implement the encodings provided by that.
WASI defines a number of built-ins which have a stable encoding, and thus can be
considered part of the ABI too.&lt;&#x2F;p&gt;
&lt;p&gt;This to me feels like the most convincing argument for why when we talk about
ABIs we cannot meaningfully separate the higher-level language (C or WIT) from
the lower-level encoding (&quot;x86-64 System V&quot; or &quot;WASI Canonical ABI&quot;). The types
defined in the higher-level language are a part of the overall contract we call
&quot;ABI&quot; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#abi-cafe&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. And those types cannot be defined without also defining a
type system to define those types in.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;abi-cafe&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gankra&#x2F;abi-cafe&quot;&gt;abi-cafe project&lt;&#x2F;a&gt; is a
good example here. It tests the compatibility of various projects which output C
ABI. And one of its trophy cases is an incompatibility between x86 linux clang,
and gcc on how &lt;code&gt;__int128&lt;&#x2F;code&gt; should be encoded when passed on-stack. And that can
only be an issue if &lt;code&gt;__int128&lt;&#x2F;code&gt; is considered part of the C ABI.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</description>
        </item>
        <item>
            <title>Iterator as an Alias</title>
            <pubDate>Wed, 08 Nov 2023 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/iterator-as-an-alias/</link>
            <guid>https://blog.yoshuawuyts.com/iterator-as-an-alias/</guid>
            <description>&lt;p&gt;This is another short post covering another short idea: I want to explain the
mechanics required to make &lt;code&gt;Iterator&lt;&#x2F;code&gt; an alias for the &lt;code&gt;Coroutine&lt;&#x2F;code&gt; trait. Making
that an alias is something Eric Holk brought up yesterday. We then talked it
through and mutually decided it probably wasn&#x27;t practical. But I thought about
it some more today, and I might have just figured out a way we could make work?
In this post I want to briefly sketch what that could look like.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;⚠️ DISCLAIMER: I&#x27;m making up a ridiculous amount of syntax in this post. None
of this is meant to be interpreted as a concrete proposal. This is just me
riffing on an idea; which is a very different flavor from some of my multi-month
research posts. Please treat this post for what it is: a way to share
potentially interesting ideas in the open. ⚠️&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;iterators-vs-coroutines&quot;&gt;Iterators vs Coroutines&lt;&#x2F;h2&gt;
&lt;p&gt;An iterator is a type which has a &lt;code&gt;next&lt;&#x2F;code&gt; method, which returns an &lt;code&gt;Option&lt;&#x2F;code&gt;.
Every time you call &lt;code&gt;next&lt;&#x2F;code&gt; it either returns &lt;code&gt;Some(T)&lt;&#x2F;code&gt; with a value, or &lt;code&gt;None&lt;&#x2F;code&gt;
to indicate it has no data to return. A coroutine is a variation of this same
idea, but fundamentally it differs in a few ways:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Coroutines can take arguments to their resume function. Which allows &lt;code&gt;yield&lt;&#x2F;code&gt; statements to evaluate to values.&lt;&#x2F;li&gt;
&lt;li&gt;Coroutines can return a different type than they yield. Iterators can only yield a type, but will always return &lt;code&gt;()&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Just so we&#x27;re able to reference it throughout this post, here are the
(simplified) signatures:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The iterator trait
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Iterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The coroutine trait
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Coroutine&amp;lt;R&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Yield;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Return;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;resume&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;arg&lt;&#x2F;span&gt;&lt;span&gt;: R) -&amp;gt; CoroutineState&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Yield, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Return&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The enum returned by the coroutine
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;CoroutineState&amp;lt;Y, R&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    Yielded(Y),
&lt;&#x2F;span&gt;&lt;span&gt;    Complete(R),
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Because it&#x27;s useful to show, here&#x27;s roughly what (I imagine) it could look like
to implement both iterators and coroutines using generator function notation:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Returning an iterator
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; (syntax example, entirely made up, not an actual proposal)
&lt;&#x2F;span&gt;&lt;span&gt;gen &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;eat_food&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; Cat) -&amp;gt; yields Purr {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                            ^          ^
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                            |          |
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                            |  The type yielded (output)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                            |
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                      The return type is always `()`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;  
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; yield a `Purr` ten times
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;yield&lt;&#x2F;span&gt;&lt;span&gt; Purr::new();
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Returning a co-routine
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; (syntax example; entirely made up, not an actual proposal)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;gen&lt;&#x2F;span&gt;&lt;span&gt;(Food) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;eat_food&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; Cat) -&amp;gt; Nap yields Purr {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ^                                   ^          ^
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; |                                   |          |
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; |                                   |  The type yielded (output)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; |                                   |
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; |                           The return type (output)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; |
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The type `yield` resumes with (input)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Every time we yield a `Purr`, yield resumes with `Food`.
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; food = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;yield&lt;&#x2F;span&gt;&lt;span&gt; Purr::new();
&lt;&#x2F;span&gt;&lt;span&gt;        cat.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;eat&lt;&#x2F;span&gt;&lt;span&gt;(food);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    Nap::new() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; We end the function by returning a `Nap`
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are probably better ways of writing this. For example: imo the types
passed to &lt;code&gt;yield&lt;&#x2F;code&gt; should be a special entry in the arguments list. We can
possibly drop the &lt;code&gt;-&amp;gt;&lt;&#x2F;code&gt; requirement for iterator-returning generator functions.
And using &lt;code&gt;gen&lt;&#x2F;code&gt; as a prefix probably isn&#x27;t necessary either. But that&#x27;s all
stuff we can figure out later. I at least wanted to make sure folks had had an
opportunity to see what functionality coroutines provide when writing generator
functions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;iterators-as-an-alias-for-coroutines&quot;&gt;Iterators as an alias for Coroutines&lt;&#x2F;h2&gt;
&lt;p&gt;Practically speaking this means that co-routines are a superset of functionality
of iterators. Enough so that if we squint we might think see it work out. We can
recreate the iterator trait if we implement a coroutine with this signature:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Coroutine&amp;lt;()&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;MyIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Yield = SomeType;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Return = ();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;resume&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;arg&lt;&#x2F;span&gt;&lt;span&gt;: ()) -&amp;gt; CoroutineState&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Yield, ()&amp;gt; { .. }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s tempting to think we could create a trait alias for this. But we run into
trouble here: the coroutine trait wants to be able to return a &lt;code&gt;CoroutineState&lt;&#x2F;code&gt;.
While &lt;code&gt;Iterator&lt;&#x2F;code&gt; is hard-coded to return &lt;code&gt;Option&lt;&#x2F;code&gt;. And we can&#x27;t change the existing &lt;code&gt;Iterator&lt;&#x2F;code&gt; trait to take anything but an option. So what should we do here.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fallible-functions&quot;&gt;Fallible functions&lt;&#x2F;h2&gt;
&lt;p&gt;We can&#x27;t change &lt;code&gt;Iterator&lt;&#x2F;code&gt;, but we &lt;em&gt;can&lt;&#x2F;em&gt; change &lt;code&gt;Coroutine&lt;&#x2F;code&gt;. What if rather than
hard-coding that it returned a &lt;code&gt;CoroutineState&lt;&#x2F;code&gt;, we instead said that it could
return anything which implements the &lt;code&gt;Try&lt;&#x2F;code&gt; trait? &lt;code&gt;Try&lt;&#x2F;code&gt; is implemented for both
not only &lt;code&gt;Option&lt;&#x2F;code&gt;, but also &lt;code&gt;CoroutineState&lt;&#x2F;code&gt;! And if we had &lt;code&gt;try&lt;&#x2F;code&gt; or &lt;code&gt;throws&lt;&#x2F;code&gt;
functions, we could make that configurable like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The coroutine trait
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Coroutine&amp;lt;R&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Yield;
&lt;&#x2F;span&gt;&lt;span&gt;    try &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;resume&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;arg&lt;&#x2F;span&gt;&lt;span&gt;: R) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Yield throws { .. }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;edit(2023-12-01)&lt;&#x2F;strong&gt;: Yosh from the future here. Scott McMurray helpfully
provided this desugaring of what an un-handwaved desugaring of this signature
could look like. Crucially it shows that we could have a fully generic &lt;code&gt;throws&lt;&#x2F;code&gt;
clause without defining what exactly it throws:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The coroutine trait
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Coroutine&amp;lt;R&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Yield;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;resume&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;arg&lt;&#x2F;span&gt;&lt;span&gt;: R) -&amp;gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Residual as ops::Residual&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Yield&amp;gt;&amp;gt;::TryType { .. }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;del&gt;I&#x27;m super hand-waving things away here&lt;&#x2F;del&gt;. But roughly what I&#x27;m meaning to describe
here is that this can return any type implementing &lt;code&gt;Try&lt;&#x2F;code&gt; which returns
&lt;code&gt;Self::Yield&lt;&#x2F;code&gt;, without describing the specific &lt;code&gt;Try::Residual&lt;&#x2F;code&gt; type. Meaning
that could equally be an &lt;code&gt;Option&lt;&#x2F;code&gt;, a &lt;code&gt;CoroutineState&lt;&#x2F;code&gt;, or a &lt;code&gt;Result&lt;&#x2F;code&gt;. The next
function should not distinguish between those. If we take that path, then we
could use that to rewrite the &lt;code&gt;Iterator&lt;&#x2F;code&gt; trait as an alias for &lt;code&gt;Coroutine&lt;&#x2F;code&gt;. We
don&#x27;t have a syntax for this, so I&#x27;ll just make up a syntax based on &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;109417&quot;&gt;return
type notation&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; A trait alias, hard-coding both the return type and resume argument to `()`.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Iterator = Coroutine&amp;lt;(), next(..) -&amp;gt; Self::Yield throws None&amp;gt;;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There&#x27;s probably a better way of writing this. But syntax is something we can
figure out. Semantically this would make the two equivalent, and it should be
possible to write a way to make these work the same way.&lt;&#x2F;p&gt;
&lt;p&gt;Also on a quick syntactical note: the &lt;code&gt;throws None&lt;&#x2F;code&gt; syntax here would operate
from the assumption that the right syntax to declare which type of residual
you&#x27;re targeting is by writing a refinement. So to use &lt;code&gt;Option&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; as the &lt;code&gt;Try&lt;&#x2F;code&gt;
type, you&#x27;d write &lt;code&gt;throws None&lt;&#x2F;code&gt;. For &lt;code&gt;Result&amp;lt;T, E&amp;gt;&lt;&#x2F;code&gt; you&#x27;d write &lt;code&gt;throws Err(E)&lt;&#x2F;code&gt;.
And so on. That way if you strip the &lt;code&gt;throws Ty&lt;&#x2F;code&gt; notation, you&#x27;d be left with
the base function signature. In a fun mirrored sort of way, I don&#x27;t think we&#x27;d
need to prefix fallible functions with a &lt;code&gt;try fn&lt;&#x2F;code&gt; notation. Just writing
&lt;code&gt;throws&lt;&#x2F;code&gt; in the return type should be enough. I think the same should be true
for generator functions too; just writing &lt;code&gt;yields T&lt;&#x2F;code&gt; in the signature should be
enough.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;support-for-pin&quot;&gt;Support for pin&lt;&#x2F;h2&gt;
&lt;p&gt;Now, we&#x27;ve gone through an entire post to show how we could turn &lt;code&gt;Iterator&lt;&#x2F;code&gt; into
an alias for &lt;code&gt;Coroutine&lt;&#x2F;code&gt;. But there is one more detail we&#x27;ve skipped over: in
the compiler the &lt;code&gt;Coroutine&lt;&#x2F;code&gt; trait is used to implement future state machines
with, created using the &lt;code&gt;async&lt;&#x2F;code&gt; keyword. In order for borrows to work across
&lt;code&gt;.await&lt;&#x2F;code&gt; points in async functions, the &lt;code&gt;Coroutine&lt;&#x2F;code&gt; trait needs to support
self-references. Today that&#x27;s done using the &lt;code&gt;Pin&lt;&#x2F;code&gt; self-type, which means the
actual signature of &lt;code&gt;Coroutine&lt;&#x2F;code&gt; today is:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Coroutine&amp;lt;R&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Yield;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Return;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;resume&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;arg&lt;&#x2F;span&gt;&lt;span&gt;: R) -&amp;gt; CoroutineState&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Yield, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Return&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;        ^ this changed
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So &lt;code&gt;Coroutines&lt;&#x2F;code&gt; must be able to express self-references. And iterators currently
don&#x27;t support that. Which means we need to find a way to bridge the two. Luckily
this is something we might be able to resolve if we consider pinning as an
orthogonal capability which we can express as a &lt;a href=&quot;https:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2023&#x2F;03&#x2F;03&#x2F;trait-transformers-send-bounds-part-3&quot;&gt;trait
transformer&lt;&#x2F;a&gt;.
Ideally what we&#x27;d do is make &lt;code&gt;Coroutine&lt;&#x2F;code&gt; and by extension &lt;code&gt;Iterator&lt;&#x2F;code&gt; generic
over: &quot;may be self-referential&quot;. I talk about this more in my latest post on the
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-iterator-trait&#x2F;#self-referential-iterators&quot;&gt;async
trait&lt;&#x2F;a&gt;;
specifically pointing out that async iterators don&#x27;t need to be self-referential -
and generator functions probably do want to be able to have self-references.
Making &lt;code&gt;Iterator&lt;&#x2F;code&gt; an alias for &lt;code&gt;Coroutine&lt;&#x2F;code&gt; further reinforces that requirement.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;This was a quick post to illustrate a way we could make &lt;code&gt;Iterator&lt;&#x2F;code&gt; a more
narrowly scoped alias for &lt;code&gt;Coroutine&lt;&#x2F;code&gt;. I&#x27;m not sure we should do this; from my
perspective we have a few options:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Never stabilize the co-routine trait. This is probably fine, since being able
to pass arguments to &lt;code&gt;yield&lt;&#x2F;code&gt; or change the return type from the yield type don&#x27;t
seem like major features. Useful, but not &lt;em&gt;critical&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Implement &lt;code&gt;Coroutine&lt;&#x2F;code&gt; as a superset of &lt;code&gt;Iterator&lt;&#x2F;code&gt;. Keeping both, but using
&lt;a href=&quot;https:&#x2F;&#x2F;without.boats&#x2F;blog&#x2F;iterator-generator&#x2F;&quot;&gt;blanket impls&lt;&#x2F;a&gt; make both work
with one another. It&#x27;s feasible, but it feels like we&#x27;re creating &quot;V2&quot;
interfaces which aren&#x27;t interchangeable. You could pass an iterator everywhere
a generator was accepted. But you couldn&#x27;t pass a generator everywhere an
iterator was accepted - unless we carve out a special exception just for this,
which seems like a pretty bad hack.&lt;&#x2F;li&gt;
&lt;li&gt;Make &lt;code&gt;Iterator&lt;&#x2F;code&gt; an alias for &lt;code&gt;Coroutine&lt;&#x2F;code&gt;. That&#x27;s what this post is about. It
would be the way we bring some of the core unstable functionality out of the
stdlib and make it available to users. Without creating an &quot;iterator v2&quot;
trait. If we&#x27;re serious about ever wanting to stabilize Coroutines, this seems
preferable.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;A nice side-effect of this approach is that we could use this as a way to
normalize our syntax as well. Right now we&#x27;re discussing adding &quot;generator
functions&quot; in the 2024 edition. But we&#x27;re making a distinction between
&quot;iterators&quot;, &quot;generators&quot;, and &quot;co-routines&quot;. If we were to adopt the aliasing
model, then the iterator trait would be the same as the generator trait. And we
would no longer have a need for another, separate concept for &quot;co-routines&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;I for one like the idea that a &quot;generator function&quot; returns an &lt;code&gt;impl Generator&lt;&#x2F;code&gt;.
And even if I don&#x27;t think that working on that should be a priority, I like that
we might now have a mechanism to make this a reality by creating a trait alias,
hard-coding certain params, and relying on the &lt;code&gt;Try&lt;&#x2F;code&gt; trait.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>What is a team?</title>
            <pubDate>Wed, 08 Nov 2023 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/what-is-a-team/</link>
            <guid>https://blog.yoshuawuyts.com/what-is-a-team/</guid>
            <description>&lt;p&gt;&lt;em&gt;update (2023-11-08): I&#x27;ve swapped the usage of &quot;horizontal&quot; and &quot;vertical&quot; in this post based on feedback.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This is going to be an ultra-short post to share an idea I&#x27;ve been mulling over
in my head for a while. Yesterday I raised the question again about WG Async
getting checkboxes for approval on decisions. For the past five or so years
we&#x27;ve had a version of the async working group driving the design of async Rust.
With the past three years being a lot more organized, with a steady roster,
leadership, and mandate. WG Async getting the ability to set checkboxes for
approval would mostly just be a formalization of the existing role we play in
the project.&lt;&#x2F;p&gt;
&lt;p&gt;However, in order to give checkboxes to the Async WG there is a question
about the way it should integrate into the project. Historically we&#x27;ve
distinguished between: top-level &quot;teams&quot;, and domain-specific &quot;working groups&quot;.
Teams are formal, first-class entities with voting rights. While working-groups
are not. This current structure still exists in the project, and so in order for
WG Async to get checkboxes we&#x27;d need to become a &quot;team&quot;. And with that there is
also a question about whether we should be a sub-team (like T-Types) or a
top-level team.&lt;&#x2F;p&gt;
&lt;p&gt;Top-level teams get a seat on the council. Sub-teams are only represented on the
council by their parent teams. In the case of T-Types the parent teams are
&quot;Lang&quot; and &quot;Compiler&quot;. In the case of WG Async the parent teams should be at
least &quot;Lang&quot; and &quot;Libs-API&quot;; but arguably also &quot;Compiler&quot; since we tend to
implement the features we&#x27;ve designed.&lt;&#x2F;p&gt;
&lt;p&gt;And this is where I think the current model runs into trouble. Ideally we&#x27;d
think of the organization hierarchy as a tree: there are teams and there are
sub-teams. But because sub-teams can have multiple parents, our tree is really a
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;graphs&#x2F;#acyclic-graphs&quot;&gt;DAG&lt;&#x2F;a&gt;. And that becomes pretty complex to reason about. So instead I want to
propose an alternate model to our organizational DAG: I think we might be better
off reasoning in terms of &lt;em&gt;vertical&lt;&#x2F;em&gt; and &lt;em&gt;horizontal&lt;&#x2F;em&gt; teams.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;vertical teams&lt;&#x2F;strong&gt;: These are teams such as Lang, Libs, Compiler, and Cargo.
They are their a domain in their own right, and largely focus on one area of work.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;horizontal teams&lt;&#x2F;strong&gt;: These are teams such as Types, Async, and possibly also
Moderation. These are teams whose domain spans across multiple vertical teams, but
rather than going broad - they specialize in a specific subject.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Categorizing teams like this doesn&#x27;t directly help answer questions about who
should have a seat on the council, nor things like membership. Those are
questions of policy, and I&#x27;m intentionally keeping that out of scope for this
post. But I hope it can help us explain why teams like &quot;Async&quot; feel different
from teams like &quot;Compiler&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Specifically I also believe that horizontal teams can help fill the gaps left
between verticals. The Types Team exists because we identified that it&#x27;s not
enough to think about the language, or the compiler - but there is a need to
also consider how the two interact. Similarly: WG Async doesn&#x27;t just consider
the async language, library, or compiler aspects. It needs to consider how the
language features will be implemented, and how that in turn will affect
libraries.&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t know what we want to name these groups. In my opinion both vertical and
horizontal teams should be teams in their own right; with neither being &quot;more
real&quot; than the other. But as I&#x27;ve said: if we were to adopt that we&#x27;d need to
reason about a bunch more things, because the current project structure attaches
certain things to &quot;top-level&quot; teams right now.&lt;&#x2F;p&gt;
&lt;p&gt;There is also a final question about the difference between &quot;teams&quot; and
&quot;initiatives&quot;. The way I&#x27;m reasoning about those is as follows:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;teams&lt;&#x2F;strong&gt;: Permanent in nature. Exist for an &lt;em&gt;unbounded amount of time&lt;&#x2F;em&gt;, cover
a broad area, and have a relatively steady membership.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;initiatives&lt;&#x2F;strong&gt;: Ephemeral in nature. Exist for a &lt;em&gt;bounded amount of time&lt;&#x2F;em&gt;,
created for a specific purpose under a team, and spun down once that purpose
has been served.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;From my perspective the purpose of an initiative is to organize specific sets of
work under a team, without requiring the people doing that work are members of
that team. For example, neither Oli nor I are members of the Lang team, but the
Effect Generics are a language-level effort. The Effects Initiative allows us to
do this work under the purview of the Lang Team without either of us being &lt;em&gt;on&lt;&#x2F;em&gt;
the Lang Team.&lt;&#x2F;p&gt;
&lt;p&gt;And that&#x27;s about it. I think if we&#x27;re going to be talking about teams and
sub-teams, I think it&#x27;s clearer to reason about teams in terms of &quot;vertical
concerns&quot; (fixed domains like &quot;compiler&quot;, &quot;language&quot;, &quot;stdlib&quot;) and &quot;horizontal
concerns&quot; (cross-cutting domains like: &quot;the type system&quot;, &quot;async support&quot;,
&quot;moderation&quot;).&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Async Iteration III: The Async Iterator Trait</title>
            <pubDate>Tue, 26 Sep 2023 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/async-iterator-trait/</link>
            <guid>https://blog.yoshuawuyts.com/async-iterator-trait/</guid>
            <description>&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;This post is part of the Async Iteration series:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-iteration&#x2F;&quot;&gt;Async Iteration I: Async Iteration Semantics&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-iterator-crate&#x2F;&quot;&gt;Async Iteration II: The Async Iterator Crate&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-iterator-trait&quot;&gt;Async Iteration III: The Async Iterator Trait&lt;&#x2F;a&gt; (this post)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Async Functions in Traits (AFIT) &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;pull&#x2F;115822&quot;&gt;are in the process of being
stabilized&lt;&#x2F;a&gt; and I figured it
would be a good time to look more closely at the properties they provide. In
this post I want to compare AFIT-based traits with poll-based traits, using the
&quot;async iterator&quot; trait as the driving example. But most everything which applies
to async iterator, will also apply to other traits such as async read and async write.&lt;&#x2F;p&gt;
&lt;p&gt;In this post I will make the case that the best direction for the stdlib is to
base its async traits on AFITs. The intended audience for this post is primarily
my fellow members of WG-Async, as well as members of T-Lang and T-Libs. To read
a summary of the findings jump ahead to the &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-iterator-trait&#x2F;#conclusion&quot;&gt;conclusion&lt;&#x2F;a&gt;. This post
assumes readers are familiar with the inner workings of Rust&#x27;s async systems, as
well as a familiarity of the tradeoffs being discussed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fn-poll-vs-async-fn&quot;&gt;fn poll_ vs async fn&lt;&#x2F;h2&gt;
&lt;p&gt;To provide some flavor to what I&#x27;m talking about, in this post we&#x27;ll be
discussing the &quot;async iterator&quot; trait, asking the question whether we should
base it on &lt;code&gt;fn poll_next&lt;&#x2F;code&gt; or &lt;code&gt;async fn next&lt;&#x2F;code&gt;. Here are both variants
side-by-side:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Using `fn poll_next`.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;AsyncIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll_next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Using `async fn next`.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;AsyncIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I expect pretty much everyone will agree that on a first look the &lt;code&gt;async fn next&lt;&#x2F;code&gt;-based trait seems easier to use. Rather than needing to think about what
&lt;code&gt;Pin&lt;&#x2F;code&gt; is, or how &lt;code&gt;Poll&lt;&#x2F;code&gt; works, we can just write our async functions the way we
usually do, and it will &lt;em&gt;just work&lt;&#x2F;em&gt;. Pretty neat!&lt;&#x2F;p&gt;
&lt;p&gt;But that&#x27;s just on the surface. Does that still hold if we look more closely?
Concerns have been raised about the performance of &lt;code&gt;async fn next&lt;&#x2F;code&gt;, claiming not
only would it perform less well. It&#x27;s also alleged that &lt;code&gt;async fn next&lt;&#x2F;code&gt; does not
provide essential features, even going so far to claim that &lt;code&gt;fn poll_next&lt;&#x2F;code&gt; is
fundamentally lower-level and thus the only reasonable choice for a systems
programming language. In the remainder of this post we&#x27;ll be going over those
claims, and show why upon closer examination they do not appear to hold.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;performance&quot;&gt;Performance&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s start with the most obvious one: performance. At its core Rust is a
systems programming language, and in order to properly cater to its niche it
tends to only provide abstractions which have comparable performance to their
hand-rolled versions. The claim is that &lt;code&gt;poll_next&lt;&#x2F;code&gt; should provide better
performance than &lt;code&gt;async fn next&lt;&#x2F;code&gt; since we&#x27;re compiling it by hand. But when
actually measured, the two approaches appear to compile to identical assembly in
various configurations - meaning they will have identical performance.&lt;&#x2F;p&gt;
&lt;p&gt;But don&#x27;t just take my word for it, we can use examples to substantiate this.
Let&#x27;s create a simple &quot;once&quot; future which holds some data, and when polled it
will return that data. Rather than using complex async&#x2F;.await machinery, we&#x27;ll
be creating a new function &lt;code&gt;poll_once&lt;&#x2F;code&gt; which constructs a dummy waker in-line
and can be used to poll a future exactly once:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;call_once&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Poll&amp;lt;Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; iter = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;once&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;poll_once&lt;&#x2F;span&gt;&lt;span&gt;(iter.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s start by evaluating what this looks like when implemented using &lt;code&gt;fn poll_next&lt;&#x2F;code&gt;. We could write this as follows:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Once&amp;lt;T&amp;gt;(Option&amp;lt;T&amp;gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; AsyncIterator &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Once&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item = T;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll_next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;_cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; SAFETY: we&amp;#39;re projecting into an unpinned field
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; this = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Pin::into_inner_unchecked(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) };
&lt;&#x2F;span&gt;&lt;span&gt;        Poll::Ready((&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; this.value).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;())
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When polled we project &lt;code&gt;Self&lt;&#x2F;code&gt; into its fields, which is just the &lt;code&gt;Option&lt;&#x2F;code&gt; type.
We then call &lt;code&gt;.take&lt;&#x2F;code&gt; to extract the value, or panic if there is none. This
should be fairly straight forward. If &lt;code&gt;poll_once&lt;&#x2F;code&gt; creates a non-atomic dummy
waker (this is just the first example), the compiler will compile this code down
to the following x86 assembly (&lt;a href=&quot;https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;4n1G1xP3f&quot;&gt;compiler explorer&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;asm&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-asm &quot;&gt;&lt;code class=&quot;language-asm&quot; data-lang=&quot;asm&quot;&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;example::call_once:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mov     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;eax&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mov     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;edx&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;ret
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This assembly basically means: &lt;em&gt;&quot;Hey I&#x27;ve got the constant &#x27;12&#x27; over here -
please move it into the return registry and then exit the function&quot;&lt;&#x2F;em&gt;. That&#x27;s
about the smallest this function can be without being inlined. Now let&#x27;s see
what happens if we implement this code using &lt;code&gt;async fn next&lt;&#x2F;code&gt;.  Instead of &lt;code&gt;fn poll_next&lt;&#x2F;code&gt; we can use an async function directly:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Once&amp;lt;T&amp;gt;(Option&amp;lt;T&amp;gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; AsyncIterator &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Once&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item = T;
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s nice we don&#x27;t have to perform pin projections anymore (more on that later).
But what&#x27;s the performance like? Well, if this was slower we&#x27;d expect it to
generate more assembly. So let&#x27;s take a look (&lt;a href=&quot;https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;459x69cYc&quot;&gt;compiler explorer&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;asm&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-asm &quot;&gt;&lt;code class=&quot;language-asm&quot; data-lang=&quot;asm&quot;&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;example::call_once:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mov     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;eax&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mov     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;edx&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;ret
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The assembly is identical! Why is that? Well, for one: the Rust compiler is
pretty good at generating fast code. But we&#x27;re also in a bit of a simplified
environment. So far in  our examples we&#x27;ve not using &quot;real&quot; thread-safe wakers,
instead basing our wakers on &lt;code&gt;Rc&lt;&#x2F;code&gt;. What happens if we switch to &lt;code&gt;Arc&lt;&#x2F;code&gt;-based
wakers? Here&#x27;s the link to a &lt;a href=&quot;https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;KffEs9sWT&quot;&gt;compiler
explorer&lt;&#x2F;a&gt; comparing the two. It now generates a
lot more assembly than before (yay atomics), but luckily we can use &lt;code&gt;diff(1)&lt;&#x2F;code&gt; to
compare the output:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;asm&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-asm &quot;&gt;&lt;code class=&quot;language-asm&quot; data-lang=&quot;asm&quot;&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;example::call_once:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;        ; 21 lines of assembly + calls to another 118 lines
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;yosh@MacBook-Pro&lt;&#x2F;span&gt;&lt;span&gt; scratch % pbpaste &amp;gt; one.rs
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;yosh@MacBook-Pro&lt;&#x2F;span&gt;&lt;span&gt; scratch % pbpaste &amp;gt; two.rs
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;yosh@MacBook-Pro&lt;&#x2F;span&gt;&lt;span&gt; scratch % diff one.rs two.rs
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;yosh@MacBook-Pro&lt;&#x2F;span&gt;&lt;span&gt; scratch %
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;diff&lt;&#x2F;code&gt; output is empty, meaning there are no differences even if we &lt;code&gt;Arc&lt;&#x2F;code&gt;s
to correctly construct our wakers, it just generates a lot more code. But okay
fine, maybe there are more differences? After all: &lt;code&gt;fn poll_next&lt;&#x2F;code&gt; has access to
the &lt;code&gt;Waker&lt;&#x2F;code&gt; and can return &lt;code&gt;Poll&lt;&#x2F;code&gt;, meaning it has low-level control over the
future state machine while &lt;code&gt;async fn next&lt;&#x2F;code&gt; does not. What happens if we want to
provide low-level control over the future state machine from &lt;code&gt;async fn next&lt;&#x2F;code&gt;?&lt;&#x2F;p&gt;
&lt;p&gt;Luckily we&#x27;ve stabilized a simple mechanism for this already:
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;future&#x2F;fn.poll_fn.html&quot;&gt;&lt;code&gt;std::future::poll_fn&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
This function provides the ability to access the low-level internals of &lt;em&gt;any&lt;&#x2F;em&gt;
future, including AFITs. Let&#x27;s lower our example to make use of this, shall we?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Once&amp;lt;T&amp;gt;(Option&amp;lt;T&amp;gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; AsyncIterator &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Once&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item = T;
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        future::poll_fn(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;_cx&lt;&#x2F;span&gt;&lt;span&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;* -&amp;gt; Poll&amp;lt;Option&amp;lt;T&amp;gt;&amp;gt; *&#x2F; &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; We have access to `cx` here which contains the `Waker`.
&lt;&#x2F;span&gt;&lt;span&gt;            Poll::Ready((&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.value).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;())
&lt;&#x2F;span&gt;&lt;span&gt;        }).await
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This seems simple enough: whenever we want to do anything low-level inside of an
&lt;code&gt;async fn&lt;&#x2F;code&gt;, we can use &lt;code&gt;poll_fn&lt;&#x2F;code&gt; to drop into the future state machine. This
should work not just for the async version of the iterator trait, but for &lt;em&gt;all&lt;&#x2F;em&gt;
async traits. There is more to be said about how this interacts with pinning and
self-referential types, but we&#x27;ll cover that in more detail later on in the
post. To close this out though: what does this compile
to if we call it using &quot;real&quot; wakers? (&lt;a href=&quot;https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;xnfh8j5x7&quot;&gt;compiler explorer&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;asm&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-asm &quot;&gt;&lt;code class=&quot;language-asm&quot; data-lang=&quot;asm&quot;&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;example::call_once:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;        ; 21 lines of assembly + calls to another 118 lines
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;yosh@MacBook-Pro&lt;&#x2F;span&gt;&lt;span&gt; scratch % pbpaste &amp;gt; two.rs
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;yosh@MacBook-Pro&lt;&#x2F;span&gt;&lt;span&gt; scratch % diff one.rs two.rs
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;yosh@MacBook-Pro&lt;&#x2F;span&gt;&lt;span&gt; scratch %
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s right: the output remains the same. This gives us a pretty good clue
about what is happening here. Inside the compiler &lt;code&gt;async fn next&lt;&#x2F;code&gt; is desugared
to a future, just like &lt;code&gt;fn poll_next&lt;&#x2F;code&gt; is. And because of basic inlining and
const-folding optimizations, the resulting state machines are identical - which
means that the resulting assembly is identical too. This is exactly how
zero-cost abstractions are supposed to work, and is &lt;a href=&quot;http:&#x2F;&#x2F;aturon.github.io&#x2F;tech&#x2F;2016&#x2F;08&#x2F;11&#x2F;futures&#x2F;&quot;&gt;the entire premise of Rust&#x27;s
async system&lt;&#x2F;a&gt;. If we ever find
a case where the optimizer doesn&#x27;t perform those basic optimizations we can then
treat that as a bug in the compiler - not a limitation of the design.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;self-referential-iterators&quot;&gt;Self-Referential Iterators&lt;&#x2F;h2&gt;
&lt;p&gt;When people say that &lt;em&gt;&quot;async iterator is not the async version of iterator&quot;&lt;&#x2F;em&gt;
they are correct. Well, sort of. If we look at &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;async_iter&#x2F;trait.AsyncIterator.html&quot;&gt;&lt;em&gt;existing&lt;&#x2F;em&gt;
implementations&lt;&#x2F;a&gt;
that is true: it doesn&#x27;t quite work like the async version of iterator. Instead
what it really is is the async version of &quot;pinned iterator&quot;. Which is not a
trait we currently have, but there certainly is a case to be made for it.
Instead it&#x27;s better to ask whether async iterator &lt;em&gt;should&lt;&#x2F;em&gt; be the &quot;async version
of iterator&quot; - and I certainly believe it should be &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#lang-framing&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;lang-framing&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Incidentally that has also been the framing of the trait
WG-async &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;pull&#x2F;3208&quot;&gt;has been communicating to T-lang and
T-libs&lt;&#x2F;a&gt;, who have signed off on it.
I&#x27;m not suggesting that this decision should &lt;em&gt;bind&lt;&#x2F;em&gt; us (I don&#x27;t like to rules
lawyer). What I&#x27;m instead trying to show with this is that this has been an
accepted framing of what the design should achieve for years now, and we&#x27;ve
already rejected the framing that &quot;async iterator&quot; (or &quot;stream&quot;) should be its
own special thing. That certainly can be changed again, but it is not a novel
insight by any stretch.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Let me explain what I mean by this using examples. In Rust the base iterator API
has an associated type &lt;code&gt;Item&lt;&#x2F;code&gt;, a function &lt;code&gt;next&lt;&#x2F;code&gt; which takes a mutable reference
to &lt;code&gt;self&lt;&#x2F;code&gt;, and returns an &lt;code&gt;Option&amp;lt;Self::Item&amp;gt;&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Iterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we did a direct translation to async Rust, we&#x27;d have an API which instead of
exposing an &lt;code&gt;fn next&lt;&#x2F;code&gt; exposed an &lt;code&gt;async fn next&lt;&#x2F;code&gt;. The only real difference here
is the addition of the &lt;code&gt;async&lt;&#x2F;code&gt; keyword:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;AsyncIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However, when we look at the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-core&#x2F;latest&#x2F;futures_core&#x2F;stream&#x2F;trait.Stream.html&quot;&gt;ecosystem &lt;code&gt;Stream&lt;&#x2F;code&gt;
trait&lt;&#x2F;a&gt;,
or the currently &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;async_iter&#x2F;trait.AsyncIterator.html&quot;&gt;unstable &lt;code&gt;AsyncIterator&lt;&#x2F;code&gt;
API&lt;&#x2F;a&gt; they are
not implemented in terms of &lt;code&gt;async fn next&lt;&#x2F;code&gt;. Instead they provide an &lt;code&gt;fn poll_next&lt;&#x2F;code&gt; which takes both a pinned reference to &lt;code&gt;self&lt;&#x2F;code&gt;, a mutable reference
to the waker context, and wrap the return type in &lt;code&gt;Poll&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;AsyncIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll_next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In the previous section we&#x27;ve already discussed how you can get access to the
waker context from inside an async function by using &lt;code&gt;poll_fn&lt;&#x2F;code&gt;. So we can pretty
much ignore the waker context and the &lt;code&gt;Poll&lt;&#x2F;code&gt; in the return type. That leaves the
change in the &lt;code&gt;self&lt;&#x2F;code&gt; type. Our &lt;code&gt;async fn next&lt;&#x2F;code&gt; takes &lt;code&gt;&amp;amp;mut self&lt;&#x2F;code&gt;, while this
variant takes &lt;code&gt;Pin&amp;lt;&amp;amp;mut Self&amp;gt;&lt;&#x2F;code&gt;. This isn&#x27;t necessary for the core functionality
of async iterator, since it is pinning more than needed. So simply put, what
we&#x27;ve just written is in fact the async version of this trait:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;PinnedIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here we have a non-async version of iterator which takes self as a pinned
reference. This is useful if you ever need to write an iterator which can
operate on self-referential structs. For example: if we ever start thinking of
stabilizing generator functions, we want them to be able to hold references
across &lt;code&gt;yield&lt;&#x2F;code&gt; points. That will require self-referential iterators.&lt;&#x2F;p&gt;
&lt;p&gt;An important insight of this is that the question of whether iterator should be
pinned is orthogonal to whether it is async. Which is illustrated by the fact
that we can reformulate a &quot;pinned asynchronous iterator&quot; just fine using AFITs:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;PinnedAsyncIterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This can be combined with the &lt;code&gt;poll_fn&lt;&#x2F;code&gt; function as we showed in the previous
section to recreate the low-level semantics of &lt;code&gt;fn poll_next&lt;&#x2F;code&gt;, providing access
to both a pinned self-type and the future&#x27;s waker argument. To put it plainly:
&lt;strong&gt;&quot;is async&quot; and &quot;is pinned&quot; are orthogonal features, and &lt;code&gt;fn poll_next&lt;&#x2F;code&gt;
needlessly combines both&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;unpin-bounds&quot;&gt;Unpin Bounds&lt;&#x2F;h2&gt;
&lt;p&gt;People occasionally ask me about the &lt;code&gt;Unpin&lt;&#x2F;code&gt; trait when I talk about async
versions of traits. For example if you compare
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.Iterator.html#tymethod.next&quot;&gt;&lt;code&gt;Iterator::next&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
and
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;latest&#x2F;futures&#x2F;prelude&#x2F;stream&#x2F;trait.StreamExt.html#method.next&quot;&gt;&lt;code&gt;futures::stream::StreamExt::next&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;,
you will see that the latter has an extra &lt;code&gt;where Self: Unpin&lt;&#x2F;code&gt; bound.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `Iterator::next`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `FuturesExt::next`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Next&amp;lt;&amp;#39;_, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;: Unpin; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; This is different
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This extra &lt;code&gt;Unpin&lt;&#x2F;code&gt; bound is only needed when a trait is implemented in terms of
poll functions - which by design take &lt;code&gt;Pin&amp;lt;&amp;amp;mut Self&amp;gt;&lt;&#x2F;code&gt;. And so we need a way to
later on opt out of those bounds. You can see this same mechanism in action with
the other poll-based traits, such as
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;latest&#x2F;futures&#x2F;io&#x2F;trait.AsyncWriteExt.html#method.write&quot;&gt;&lt;code&gt;AsyncWriteExt::write&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
which also has a &lt;code&gt;Self: Unpin&lt;&#x2F;code&gt; bound.&lt;&#x2F;p&gt;
&lt;p&gt;Instead if we recognize that the async counterparts to Rust&#x27;s core traits don&#x27;t
actually need to be pinned in order to be implemented, we can drop &lt;code&gt;Pin&amp;lt;&amp;amp;mut Self&amp;gt;&lt;&#x2F;code&gt; from the signature. And since our type isn&#x27;t pinned to begin with,
we no longer have to opt-out of it being pinned via &lt;code&gt;Unpin&lt;&#x2F;code&gt; meaning all the
extra &lt;code&gt;Unpin&lt;&#x2F;code&gt; bounds go away. You can see this in action in the
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-iterator&#x2F;latest&#x2F;async_iterator&#x2F;trait.Iterator.html&quot;&gt;&lt;code&gt;async-iterator&lt;&#x2F;code&gt;
crate&lt;&#x2F;a&gt;
which provides a diverse range of methods on async iterator, none of which
require additional &lt;code&gt;Unpin&lt;&#x2F;code&gt; bounds to function.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;implementation-vs-usage&quot;&gt;Implementation vs Usage&lt;&#x2F;h2&gt;
&lt;p&gt;To stay on the topic of API-shapes: one major downside of &lt;code&gt;fn poll_next&lt;&#x2F;code&gt; is that
the &quot;method to implement&quot; and &quot;method to call&quot; are different methods. In the
regular iterator trait, there is only one method &lt;code&gt;next&lt;&#x2F;code&gt; which is both
implemented and called. Instead the poll-API is only meant to be &lt;em&gt;implemented&lt;&#x2F;em&gt;,
and in virtually all cases the &lt;code&gt;next&lt;&#x2F;code&gt; function is the one you want to call. This
is a major deviation of how all other traits work in the stdlib today.&lt;&#x2F;p&gt;
&lt;p&gt;This isn&#x27;t just limited to async &lt;code&gt;Iterator&lt;&#x2F;code&gt; either. Presumably we&#x27;d want to
adapt this approach for &lt;em&gt;all&lt;&#x2F;em&gt; traits in the stdlib. That means users of async
Rust would need to think of traits in the stdlib as somehow &quot;different&quot;, and
remember that they cannot directly implement the methods they&#x27;re calling. Among
others, the following APIs would be affected:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;poll-based stdlib traits&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;trait name&lt;&#x2F;th&gt;&lt;th&gt;to be implemented&lt;&#x2F;th&gt;&lt;th&gt;to be called&lt;&#x2F;th&gt;&lt;th&gt;is same?&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;async Read&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn poll_read&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;async fn read&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;❌&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;async Write&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn poll_write&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;async fn write&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;❌&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;async BufWrite&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn poll_fill_buf&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;async fn fill_buf&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;❌&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;async Seek&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn poll_seek&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;async fn seek&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;❌&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Instead, if we base these traits on &lt;code&gt;async fn&lt;&#x2F;code&gt;, the method to implement and the
method to call are identical. And as we&#x27;ve covered earlier, if anyone would want
to manually author a &lt;code&gt;poll&lt;&#x2F;code&gt;-based state machine for any of these traits,
&lt;code&gt;poll_fn&lt;&#x2F;code&gt; provides a uniform way to do so for &lt;em&gt;all&lt;&#x2F;em&gt; async traits:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;async-fn based stdlib traits&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;trait name&lt;&#x2F;th&gt;&lt;th&gt;to be implemented&lt;&#x2F;th&gt;&lt;th&gt;to be called&lt;&#x2F;th&gt;&lt;th&gt;is same?&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;async Read&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;async fn read&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;async fn read&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;✅&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;async Write&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;async fn write&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;async fn write&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;✅&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;async BufWrite&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;async fn fill_buf&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;async fn fill_buf&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;✅&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;async Seek&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;async fn seek&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;async fn seek&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;✅&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;This might seem like a minor point, but we have to consider that every deviation
from existing norms is a point of friction for users. To zoom out slightly: I
don&#x27;t believe that async Rust inherently needs to be much more difficult than
regular Rust. But the missing language features, combined with subtle differences
like these, eventually add up and create an experience which is sufficiently
different that the resulting system feels like an entirely different language.
When in reality it does not need to be. For good measure here are the existing
non-async stdlib traits:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;non-async stdlib traits&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;trait name&lt;&#x2F;th&gt;&lt;th&gt;to be implemented&lt;&#x2F;th&gt;&lt;th&gt;to be called&lt;&#x2F;th&gt;&lt;th&gt;is same?&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Read&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn read&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn read&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;✅&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Write&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn write&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn write&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;✅&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;BufWrite&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn fill_buf&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn fill_buf&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;✅&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Seek&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn seek&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn seek&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;✅&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;object-safety&quot;&gt;Object Safety&lt;&#x2F;h2&gt;
&lt;p&gt;So far we&#x27;ve only discussed the implementation side of the traits. However that
isn&#x27;t the complete story, and we need to consider auto traits and other subtle
semantics too. So let&#x27;s start looking at those, starting with
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;reference&#x2F;items&#x2F;traits.html#object-safety&quot;&gt;object-safety&lt;&#x2F;a&gt;.
Out of the box &lt;code&gt;poll&lt;&#x2F;code&gt;-based traits are dyn-safe. Say we wanted to implement a
poll-based version of async iterator which can produce an infinite number of
meows, we could create a dyn variant like so
(&lt;a href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=stable&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=57cd30432f72a90dac7fcd9099887d0f&quot;&gt;playground&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;AsyncIterator &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item = String;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll_next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;_cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        Poll::Ready(Some(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;meow&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;()))
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;dyn_iter&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Box&amp;lt;dyn AsyncIterator&amp;lt;Item = String&amp;gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    Box::new(Cat {})
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the same as any other dyn-safe trait, and doesn&#x27;t requiring any
additional steps. Nice! Now what happens if we try and rewrite it to use &lt;code&gt;async fn next&lt;&#x2F;code&gt;.  Well, we would probably try and write it like so
(&lt;a href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=nightly&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=91218b22577f1876fecfdcb906913a79&quot;&gt;playground&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;feature&lt;&#x2F;span&gt;&lt;span&gt;(async_fn_in_trait)]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;AsyncIterator &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item = String;
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        Some(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;meow&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;())
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;dyn_iter&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Box&amp;lt;dyn AsyncIterator&amp;lt;Item = String&amp;gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    Box::new(Cat {})
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However if we now try and compile this code we now get the following error:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;error[E0038]: the trait `AsyncIterator` cannot be made into an object
&lt;&#x2F;span&gt;&lt;span&gt;  --&amp;gt; src&#x2F;lib.rs:16:22
&lt;&#x2F;span&gt;&lt;span&gt;   |
&lt;&#x2F;span&gt;&lt;span&gt;16 | fn dyn_iter() -&amp;gt; Box&amp;lt;dyn AsyncIterator&amp;lt;Item = String&amp;gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `AsyncIterator` cannot be made into an object
&lt;&#x2F;span&gt;&lt;span&gt;   |
&lt;&#x2F;span&gt;&lt;span&gt;note: for a trait to be &amp;quot;object safe&amp;quot; it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit &amp;lt;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;reference&#x2F;items&#x2F;traits.html#object-safety&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;  --&amp;gt; src&#x2F;lib.rs:5:14
&lt;&#x2F;span&gt;&lt;span&gt;   |
&lt;&#x2F;span&gt;&lt;span&gt;3  | trait AsyncIterator {
&lt;&#x2F;span&gt;&lt;span&gt;   |       ------------- this trait cannot be made into an object...
&lt;&#x2F;span&gt;&lt;span&gt;4  |     type Item;
&lt;&#x2F;span&gt;&lt;span&gt;5  |     async fn next(&amp;amp;mut self) -&amp;gt; Option&amp;lt;Self::Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;   |              ^^^^ ...because method `next` is `async`
&lt;&#x2F;span&gt;&lt;span&gt;   = help: consider moving `next` to another trait
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This would not happen if we were using the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-trait&#x2F;latest&#x2F;async_trait&#x2F;&quot;&gt;async-trait
crate&lt;&#x2F;a&gt;, it only happens if we
use the AFIT language feature. But what exactly is going on here? In order for
async traits to work in dyn contexts, we need to find a place to store them
first. In the &lt;code&gt;async-trait&lt;&#x2F;code&gt; crate this is always a &lt;code&gt;Box&lt;&#x2F;code&gt;, but in stable Rust we
can&#x27;t just do that because we&#x27;ve pinky-promised not to perform any &quot;hidden&quot;
allocations &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#past&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Solving this is pretty complicated, and will require a
feature like
&lt;a href=&quot;https:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2022&#x2F;03&#x2F;29&#x2F;dyn-can-we-make-dyn-sized&#x2F;&quot;&gt;&lt;code&gt;dyn*&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
to land. With &lt;code&gt;dyn*&lt;&#x2F;code&gt; rather than calling &lt;code&gt;Box::new&lt;&#x2F;code&gt; you&#x27;d need to call a &quot;dyn
adapter&quot; instead. &lt;a href=&quot;https:&#x2F;&#x2F;theincredibleholk.org&#x2F;blog&#x2F;2022&#x2F;12&#x2F;19&#x2F;async-fn-in-trait-object-update&#x2F;&quot;&gt;For
example&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;past&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Though in the past we &lt;em&gt;have&lt;&#x2F;em&gt; used allocations in language features as
placeholders: that&#x27;s how &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; was originally stabilized in 2019. It
wasn&#x27;t until a year or so later that support landed for async functions which
didn&#x27;t box in their desugaring.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;dyn_iter&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Box&amp;lt;dyn AsyncIterator&amp;lt;Item = String&amp;gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    Boxed::new(Cat {}) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; NOTE: using the `Boxed` dyn-adapter, not `Box`.
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Needing to replace &lt;code&gt;Box::new&lt;&#x2F;code&gt; with &lt;code&gt;Boxed::new&lt;&#x2F;code&gt; is not a major difference. And
it&#x27;s still unclear what the upper bound on the ergonomics of dyn async traits
are, since work on it has been paused for the past year in favor of stabilizing
AFIT first. But it&#x27;s going to be pretty confusing if certain async traits
require a &lt;code&gt;Box&lt;&#x2F;code&gt;, but other async traits require a &lt;code&gt;Boxed&lt;&#x2F;code&gt; notation.&lt;&#x2F;p&gt;
&lt;p&gt;I believe the better direction is for all async traits in the stdlib to use the
same mechanism to work with dyn, even if initially it&#x27;s slightly less convenient
at first. We can then gradually work on improving those ergonomics for all async
traits, both in the stdlib and ecosystem. This ensures consistency and enables
us to design solutions which are shared by the entire async ecosystem and
preventing a possible permanent bifurcation of the async trait space.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cancellation-safety&quot;&gt;&quot;Cancellation Safety&quot;&lt;&#x2F;h2&gt;
&lt;p&gt;Another subtle outcome here is the interaction between async traits and the
property has been historically called: &quot;cancellation safety&quot;. I&#x27;m putting it in
quotes because the property is not actually about whether it is &quot;safe to cancel&quot;
a future. A few months ago I &lt;a href=&quot;https:&#x2F;&#x2F;docs.google.com&#x2F;presentation&#x2F;d&#x2F;1CObHaEu1OnXhTEFs3RmuUQHJj_Uw9HOqWHqmnod6YXc&#x2F;edit?usp=sharing&quot;&gt;gave a
talk&lt;&#x2F;a&gt;
about this, which I&#x27;ll summarize in this section. I&#x27;ll explain what
&quot;cancellation safety&quot; is, how it currently falls short, and how may be able to
fix those shortcomings. I particularly want to show how we can bring the
&quot;cancellation safety&quot; property into the type system, which could enable async
functions (including AFIT) to automatically provide it.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Cancellation safety&quot; refers to the ability to drop and recreate futures
without any &quot;side-effects&quot; being observable. It&#x27;s important to note that the word
&quot;safety&quot; in this context has nothing to do with memory safety: in the absence of
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;linear-types-one-pager&#x2F;&quot;&gt;linear types&lt;&#x2F;a&gt;, all types
in Rust must be memory-safe to drop, including futures. The &quot;safety&quot; in
&quot;cancellation safety&quot; refers to logical correctness only. Being able to drop and
recreate futures is the most relevant to the &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;futures-concurrency-3&#x2F;&quot;&gt;select!
macro&lt;&#x2F;a&gt; which commonly does
that in a loop. But it can also come in useful if you&#x27;re ever authoring future
state machines by hand.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;md&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-md &quot;&gt;&lt;code class=&quot;language-md&quot; data-lang=&quot;md&quot;&gt;&lt;span&gt;&#x2F;&#x2F;&#x2F; # Cancel safety
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&#x2F;&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&#x2F;&#x2F; This method is cancel safe. If you use it as the event in a
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&#x2F;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;`tokio::select!`&lt;&#x2F;span&gt;&lt;span&gt; statement and some other branch completes
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&#x2F;&#x2F; first, then it is guaranteed that no data was read.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As I&#x27;ve mentioned, &quot;cancellation safety&quot; as a property currently only exists in
documentation. This means that in order to learn whether you can drop and
recreate futures without any actions you need to consult the documentation for
the method. The difference between &lt;code&gt;async fn next&lt;&#x2F;code&gt; and &lt;code&gt;fn poll_next&lt;&#x2F;code&gt; is that
for the former the property will be documented on the implementation, whereas
for the latter the property will be documented on the trait definition.
That practically means that with &lt;code&gt;fn poll_next&lt;&#x2F;code&gt; you&#x27;ll be able to remember that
&lt;em&gt;all&lt;&#x2F;em&gt; calls to &lt;code&gt;next&lt;&#x2F;code&gt; are &quot;cancellation-safe&quot;. Whereas with &lt;code&gt;async fn next&lt;&#x2F;code&gt;
you&#x27;ll need to remember that for each implementation (or more likely: remember
which impls aren&#x27;t &quot;cancellation-safe&quot;).&lt;&#x2F;p&gt;
&lt;p&gt;But we should be legitimately asking ourselves whether using documentation for
this is the best we can do. &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;RTFM&quot;&gt;RTFM&lt;&#x2F;a&gt; is not
really how we do things in the Rust project, instead much preferring if the
compiler can tell you when you&#x27;ve messed up, which can then explain what to do
instead. This is possible because of Rust&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Type_safety&quot;&gt;&quot;type
safety&quot;&lt;&#x2F;a&gt; guarantee, and APIs such as
&lt;code&gt;select!&lt;&#x2F;code&gt; are decidedly not type-safe right now. Which is why even after
successfully compiling code, people regularly find runtime bugs in their
&lt;code&gt;select!&lt;&#x2F;code&gt; statements.&lt;&#x2F;p&gt;
&lt;p&gt;I believe a better direction would be to bring &quot;cancellation safety&quot; out of the
docs and into the type system. We could do this by introducing a new
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;rust-by-example&#x2F;trait&#x2F;supertraits.html&quot;&gt;subtrait&lt;&#x2F;a&gt;,
which I&#x27;ll refer to in this post as &lt;code&gt;AtomicFuture&lt;&#x2F;code&gt; (but we can call it anything
we like really, the semantics are what I care about most). We already have some
precedent for this in the iterator family of traits, where for example the
unstable
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.TrustedLen.html&quot;&gt;&lt;code&gt;TrustedLen&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; trait
provides additional guarantees on top of the existing &lt;code&gt;Iterator&lt;&#x2F;code&gt; trait. I
imagine this would look something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! ⚠️  This uses a placeholder name and is intended as a design-sketch only. ⚠️
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A future which performs at most a single async operation.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;AtomicFuture: Future {}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;One of the downsides of the current &quot;cancellation safety&quot; system is that we have
to manually inspect anonymous futures whether they&#x27;re cancellation-safe or not.
I believe by bringing &quot;cancellation safety&quot; into the type system the compiler
should be able to figure it out automatically if the following cases are met:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;No local state:&lt;&#x2F;strong&gt; The async context must contain at most one &lt;code&gt;.await&lt;&#x2F;code&gt;
point. That way if a future is cancelled it will never occur between two
&lt;code&gt;.await&lt;&#x2F;code&gt; points.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Virality:&lt;&#x2F;strong&gt; All futures awaited inside the &lt;code&gt;async&lt;&#x2F;code&gt; context implement the trait.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Any &lt;code&gt;async fn&lt;&#x2F;code&gt; or &lt;code&gt;async {}&lt;&#x2F;code&gt; block would automatically be able to implement
&lt;code&gt;AtomicFuture&lt;&#x2F;code&gt; if those requirements are upheld, which I believe is something
which shouldn&#x27;t be too hard to figure out from the generated state machine
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#generators&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Maybe there is a case to be made for syntax for this too; I&#x27;m not
sure. But that&#x27;s something we can figure out later.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;generators&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Also: this is something we&#x27;ll want to do regardless if we ever
get generator functions. It would be pretty bad if &lt;code&gt;gen fn&lt;&#x2F;code&gt; couldn&#x27;t
automatically implement marker traits on the type it returns.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ✅ -&amp;gt; impl Future + AtomicFuture
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12 &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ✅ -&amp;gt; impl Future + AtomicFuture
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;F: AtomicFuture&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fut&lt;&#x2F;span&gt;&lt;span&gt;: F) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;F::&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    fut.await
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ❌ -&amp;gt; impl Future
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;F: Future&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fut&lt;&#x2F;span&gt;&lt;span&gt;: F) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;F::&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    fut.await
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ❌ -&amp;gt; impl Future
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;F: AtomicFuture&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fut1&lt;&#x2F;span&gt;&lt;span&gt;: F, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fut2&lt;&#x2F;span&gt;&lt;span&gt;: F) {
&lt;&#x2F;span&gt;&lt;span&gt;    fut1.await;
&lt;&#x2F;span&gt;&lt;span&gt;    fut2.await;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The compiler will only be able to automatically figure out whether
&lt;code&gt;AtomicFuture&lt;&#x2F;code&gt; can be implemented for futures returned by &lt;code&gt;async fn&lt;&#x2F;code&gt; and
&lt;code&gt;async {}&lt;&#x2F;code&gt;. For manually implemented futures the author of the future will need
to uphold those guarantees themselves. The bar to meet there is that the future
should only perform a single operation, and then return. &lt;code&gt;read&lt;&#x2F;code&gt; is a good
example of a &quot;stateless future&quot;, while the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-concurrency&#x2F;latest&#x2F;futures_concurrency&#x2F;future&#x2F;trait.FutureExt.html#tymethod.join&quot;&gt;future &lt;code&gt;join&lt;&#x2F;code&gt;
operation&lt;&#x2F;a&gt;
is a good example of a future which is not.&lt;&#x2F;p&gt;
&lt;p&gt;As a basis I think this is pretty good, but there are still some cases we
haven&#x27;t covered yet. For example &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio&#x2F;latest&#x2F;tokio&#x2F;sync&#x2F;struct.Mutex.html#method.lock&quot;&gt;tokio&#x27;s &lt;code&gt;Mutex::lock&lt;&#x2F;code&gt;
operation&lt;&#x2F;a&gt;:
only performs one operation, but when it&#x27;s dropped and recreated it&#x27;ll be the
last in the unlock queue again - which in pathological cases could lead to
certain unlocks never being scheduled. It&#x27;s not marked &quot;cancellation-safe&quot; in
the tokio docs, but the reason for that is not covered by the rules we&#x27;ve
described so far.&lt;&#x2F;p&gt;
&lt;p&gt;I think practically we&#x27;ll want to play around with the rules a little. I don&#x27;t
think we want or even can practically nail down what a &quot;side-effect&quot; is in Rust.
But if we intentionally don&#x27;t make the presence of &lt;code&gt;AtomicFuture&lt;&#x2F;code&gt; a safety
invariant, we can probably get away by adding broad rules such as:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Cancelling and recreating an &lt;code&gt;AtomicFuture&lt;&#x2F;code&gt; should not cause logic errors&quot;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;What does that exactly mean? That&#x27;s up for interpretation. But that might be
fine for our purposes. I think it&#x27;s worth experimenting a little, so we can
settle on something that works for us. Ideally a definition which can be
automatically implemented by the compiler for async blocks and functions, but if
we can&#x27;t that&#x27;s probably also okay. The key takeaway here should be that if we
care enough about &quot;cancellation-safety&quot; to make it a guarantee of our public
APIs, we should be trying to bring it into the trait system instead.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pin-ergonomics&quot;&gt;Pin Ergonomics&lt;&#x2F;h2&gt;
&lt;p&gt;I think if we&#x27;re to have an honest conversation about poll-based APIs, we should
acknowledge that working with &lt;code&gt;Pin&lt;&#x2F;code&gt; is not a great experience for most people.
I&#x27;m a world-leading expert in async Rust, and four years post stabilization I
still regularly struggle to use it. I&#x27;ve seen folks on both T-lang and T-libs
struggle with it. I&#x27;ve seen very capable engineers at Microsoft struggle with
it. And if experienced folks struggle to use Pin, I don&#x27;t think we can
reasonably expect those with less experience to use it without much problems either.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve covered some of the unique difficulties of &lt;code&gt;Pin&lt;&#x2F;code&gt; on this blog before. I
believe pin is hard to use in part because pin inverts Rust&#x27;s usual semantics
via a combination of auto-traits and wrapper structs. Another reason is because
it relies heavily on the concept of &quot;pin-projection&quot; which requires &lt;code&gt;unsafe&lt;&#x2F;code&gt; and
is not directly represented in either the language or the stdlib. Which in turn
means that even the most common interactions with Rust&#x27;s pinning system rely
third-party ecosystem crates such as
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;pin-project&#x2F;latest&#x2F;pin_project&#x2F;&quot;&gt;pin-project&lt;&#x2F;a&gt; and until
recently &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;pin-utils&#x2F;latest&#x2F;pin_utils&#x2F;&quot;&gt;pin-utils&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We currently don&#x27;t have a clear path to fix Pin&#x27;s ergonomics. If we want Rust to
provide a way to make pin projections safe, we&#x27;ll at least need to make a
breaking change to the &lt;code&gt;Unpin&lt;&#x2F;code&gt; trait &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#breaking&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. As well as &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;safe-pin-projections-through-view-types&#x2F;&quot;&gt;a whole lot of
design
work&lt;&#x2F;a&gt; to
integrate it into the language. And while this may be something we&#x27;ll want to do
eventually, we really need to ask ourselves whether this is something we want to
do &lt;em&gt;now&lt;&#x2F;em&gt;. Because taking on one project necessarily means not taking on another.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;breaking&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;Safe pin projections in the language necessarily require that
&lt;code&gt;Unpin&lt;&#x2F;code&gt; is an &lt;code&gt;unsafe&lt;&#x2F;code&gt; trait. It&#x27;s currently not unsafe, and changing it would
be a breaking change.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;I honestly think async functions in traits, async drop, async iteration, and
async closures all are far more important things to work on right now, and they
should take priority in WG-async over directly fixing Pin&#x27;s rough edges. &lt;strong&gt;The
most effective strategy to reduce the cost of &lt;code&gt;Pin&lt;&#x2F;code&gt; we have in Rust right now is
to simply make pin less common&lt;&#x2F;strong&gt;. If &lt;code&gt;Pin&lt;&#x2F;code&gt; is only needed to implement intrusive
collections, self-referential types, and manual future state machines then for
the time being we think of it as an experts-only system. And once we have more
bandwidth we can revisit it later to tidy it up.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;evolution&quot;&gt;Evolution&lt;&#x2F;h2&gt;
&lt;p&gt;A thing that worries me in particular about &lt;code&gt;fn poll_next&lt;&#x2F;code&gt; is its inability to
co-evolve with Rust&#x27;s needs. As we&#x27;ve seen we&#x27;re not just considering adding an
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-iterator&#x2F;latest&#x2F;async_iterator&#x2F;&quot;&gt;&quot;async version of iterator&quot;&lt;&#x2F;a&gt;, we&#x27;re also talking about &quot;a pinned version
of iterator&quot;. But there are other flavors of iterator being discussed as well,
such as: &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;fallible-iterator&#x2F;0.3.0&#x2F;fallible_iterator&#x2F;&quot;&gt;&quot;a fallible version of iterator&quot;&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;lending-iterator&#x2F;latest&#x2F;lending_iterator&#x2F;&quot;&gt;&quot;a lending version of
iterator&quot;&lt;&#x2F;a&gt;, &quot;a const version of iterator&quot;, and so on. It&#x27;s impossible to
know today which requirements Rust will have ten years from now. All we really
know is that the decisions we make then will be affected by the decisions we
make today &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#success&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;success&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;Ten years ago we were unsure whether it was even possible to publish
a new systems programming language. Five years ago we were unsure whether Rust
would be able to escape its browser niche and reach mainstream adoption. Flash
forward to today, and Rust is being used in the hearts of major operating
systems (Android, Linux, and Windows). As well as every packet on the internet
more likely than not being routed through some Rust code at some point
(Cloudflare, AWS, and Azure). I don&#x27;t think we can reasonably anticipate all the
requirements Rust will face ten years from now. So I believe one of the most
important things for a programming language is to find ways to keep evolving the
language in the face of changing requirements.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Say for a second we did add an &lt;code&gt;fn poll_next&lt;&#x2F;code&gt;-based version of iterator. If we
wanted to say, add a lending version of iterator. Then we&#x27;d probably also want
to add a &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-iterator&#x2F;latest&#x2F;async_iterator&#x2F;trait.LendingIterator.html&quot;&gt;lending version of async iterator&lt;&#x2F;a&gt; too. That would be four
separate families of traits, and that&#x27;s just for three variants. If we actually
wanted to add support for &quot;pinned iterators&quot; or &quot;fallible iterators&quot; we&#x27;d be
looking at nine or maybe even seventeen different families of traits. And nobody
reasonably wants that.&lt;&#x2F;p&gt;
&lt;p&gt;This is the reason why I believe &lt;code&gt;async fn next&lt;&#x2F;code&gt; is the better direction. If we
add it to the stdlib via an effect-generic mechanism, both &quot;iterator&quot; and &quot;async
iterator&quot; could be served using a single trait which is generic over the async
effect. But we could use the same mechanism for other traits such as &lt;code&gt;Read&lt;&#x2F;code&gt; and
&lt;code&gt;Write&lt;&#x2F;code&gt;, but also maybe some less common traits like &lt;code&gt;Into&lt;&#x2F;code&gt; and &lt;code&gt;Display&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! A version of iterator which can be implemented as either sync or async.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! This uses placeholder syntax just to illustrate the idea.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;maybe_async&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Iterator {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item;
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;maybe_async&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;fn poll_next&lt;&#x2F;code&gt; forces us to duplicate existing interfaces in order to expose
those same capabilities. While &lt;code&gt;async fn next&lt;&#x2F;code&gt; enables us to extend existing
interfaces with new capabilities. It doesn&#x27;t immediately solve all of the
limitations of iterator; effect generics won&#x27;t provide an answer for how to add
support for &quot;lending&quot; or &quot;pinned&quot; iterator variants. But it provides an answer
to some other problems, like how to add support for async, const, and
fallibility. And in doing so encourages us to find similar solutions for the
problems which remain, even if we don&#x27;t yet know what they&#x27;ll look like.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post I&#x27;ve presented a case for basing the async Iterator trait on &lt;code&gt;async fn next&lt;&#x2F;code&gt; over &lt;code&gt;fn poll_next&lt;&#x2F;code&gt;. To summarize the arguments:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Performance&lt;&#x2F;strong&gt;: Iterators based on &lt;code&gt;async fn next&lt;&#x2F;code&gt; and &lt;code&gt;fn poll_next&lt;&#x2F;code&gt;
generate identical code, which means they have identical performance profiles.
Implementations which need to access the low-level future state machine of
&lt;code&gt;async fn next&lt;&#x2F;code&gt; can do so using &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;future&#x2F;fn.poll_fn.html&quot;&gt;&lt;code&gt;poll_fn&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Self-referential iterators&lt;&#x2F;strong&gt;: &lt;code&gt;fn poll_next&lt;&#x2F;code&gt; is the async version of
&lt;code&gt;PinnedIterator&lt;&#x2F;code&gt;, &lt;code&gt;async fn next&lt;&#x2F;code&gt; is the async version of &lt;code&gt;Iterator&lt;&#x2F;code&gt;. Adding a
trait for pinned async iteration could be useful, but realistically it should
mirror a synchronous &quot;pinned iterator&quot; design. And it could be written using
&lt;code&gt;async fn next&lt;&#x2F;code&gt; taking a pinned self-type.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Unpin bounds&lt;&#x2F;strong&gt;: The presence of extra &lt;code&gt;Unpin&lt;&#x2F;code&gt; bounds are a way in which
async traits presently meaningfully deviate from their synchronous counterparts.
&quot;async iterator&quot; meaningfully deviates from its synchronous
counterparts. It makes it seem like deeper changes are needed to get to the
same async functionality. By not requiring &lt;code&gt;self: Pin&amp;lt;&amp;amp;mut Self&amp;gt;&lt;&#x2F;code&gt;, no
additional &lt;code&gt;where Self: Unpin&lt;&#x2F;code&gt; bounds are required as seen on methods such as
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;latest&#x2F;futures&#x2F;prelude&#x2F;stream&#x2F;trait.StreamExt.html#method.next&quot;&gt;&lt;code&gt;StreamExt::next&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Implementation vs Usage&lt;&#x2F;strong&gt;: &lt;code&gt;async fn next&lt;&#x2F;code&gt; has one method to both
implement and use. &lt;code&gt;fn poll_next&lt;&#x2F;code&gt; requires two methods: one which must be
implemented, and another which must be called. This is inherently more
difficult to use, and as a mechanism is unique to poll functions other than
&lt;code&gt;Future&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Object Safety&lt;&#x2F;strong&gt;: &lt;code&gt;async fn next&lt;&#x2F;code&gt; and &lt;code&gt;fn poll_next&lt;&#x2F;code&gt; need to use subtly
different mechanisms to create dynamically dispatched objects. Adding support
for dynamic dispatching is still in-progress for AFITs, but that seems like
it&#x27;s mostly a matter of time. Neither approach is likely going to be much
harder to use than the other, but the subtle differences may be difficult to
internalize for users. Diagnostics seem like they&#x27;ll play an important role.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&quot;Cancellation Safety&quot;&lt;&#x2F;strong&gt;: &quot;cancellation safety&quot; is currently a
documentation-only property. If async iterator is based on &lt;code&gt;fn poll_next&lt;&#x2F;code&gt; users
can blindly assume every implementation provides a cancellation-safe &lt;code&gt;next&lt;&#x2F;code&gt;
method. If async iterator is based on &lt;code&gt;async fn next&lt;&#x2F;code&gt; users will have to check
the implementation&#x27;s docs to learn whether the &lt;code&gt;next&lt;&#x2F;code&gt; method is
&quot;cancellation-safe&quot;. However, rather than keeping &quot;cancellation-safety&quot; as a
documentation-only property, we should probably instead be working to bring
into the type system instead.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Pin Ergonomics&lt;&#x2F;strong&gt;: The &lt;code&gt;Pin&lt;&#x2F;code&gt; family of APIs in Rust is notorious for being
difficult to use. One of the most effective ways we have to reduce the
difficulty of Pin is by limiting user&#x27;s exposure to it. By basing Rust&#x27;s core
async traits on async functions we can reduce the number of pin-based APIs,
making async Rust more accessible to more people.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Evolution&lt;&#x2F;strong&gt;: &lt;code&gt;async fn next&lt;&#x2F;code&gt; can be implemented as an &lt;em&gt;extension&lt;&#x2F;em&gt; to the
existing iterator trait via effect generics. &lt;code&gt;fn poll_next&lt;&#x2F;code&gt; would most need to
be implemented as a standalone trait, resulting in a manual &lt;em&gt;duplication&lt;&#x2F;em&gt; of
the APIs. Support for async is not the last feature we&#x27;ll want to add to
iterators: there are currently ecosystem demands to support self-referential
iteration, lending iteration, and fallible iteration. It&#x27;s not practical to
add individual traits for all of these and their combinations. Nor is it
reasonable we can anticipate all needs which may arise in the future. By
extending rather than duplicating we&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I believe basing the async Iterator trait on &lt;code&gt;async fn next&lt;&#x2F;code&gt; to be superior
across all axes, and I hope this post sufficiently makes that case. In a future
post I&#x27;d like to round out this series by covering the desugaring of an async
iteration notation. Together with an RFC for effect-generic trait definitions,
this will be one of the last steps necessary step before we can re-RFC &lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rfcs&#x2F;2996-async-iterator.html&quot;&gt;RFC
2996: Async Iterator&lt;&#x2F;a&gt;
to cover the full scope of async iteration.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Eric Holk for reviewing an earlier draft of this post.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>nesting allocators</title>
            <pubDate>Wed, 09 Aug 2023 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/nesting-allocators/</link>
            <guid>https://blog.yoshuawuyts.com/nesting-allocators/</guid>
            <description>&lt;p&gt;I regularly point people to Tmandry&#x27;s 2021 post &lt;a href=&quot;https:&#x2F;&#x2F;tmandry.gitlab.io&#x2F;blog&#x2F;posts&#x2F;2021-12-21-context-capabilities&quot;&gt;&lt;em&gt;&quot;Contexts and Capabilities in
Rust&quot;&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;.
While nobody is actively working on the design at the moment, it&#x27;s more because
of prioritization than anything else. It seems like it could make certain usage
patterns a lot nicer in Rust, and one of those is probably working with custom
allocators.  I&#x27;ve been working a lot with &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Slab_allocation&quot;&gt;slab
allocators&lt;&#x2F;a&gt; recently, and I&#x27;d
love it if they were easier to work with in Rust. So I wanted to take a moment
to talk about allocators, capabilities as a language feature, and why I believe
that would work well.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;kinds-of-allocation&quot;&gt;Kinds of allocation&lt;&#x2F;h2&gt;
&lt;p&gt;Memory, at least semantically, is best thought of as a contiguous sequence of
bytes. Allocators manage these bytes and do the bookkeeping for who is using
what. Allocators can take any type of object (&quot;heterogenous types&quot;) and place
them in memory. And once we&#x27;re done with an object, the allocator will reclaim
the memory. Because not all objects are the same size this can leave gaps in
memory, so occasionally the allocator spends some time reorganizing its
internals (think: defragmentation). In practical terms, every program wants to
have a single allocator to manage the &lt;em&gt;entire&lt;&#x2F;em&gt; program. This root allocator is
what we refer to as the &lt;em&gt;global allocator&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;But where global allocators are &lt;em&gt;great&lt;&#x2F;em&gt;, they are not &lt;em&gt;perfect&lt;&#x2F;em&gt;. Typically when
we write programs we&#x27;ll see usage patterns in our main loop. For example: if
we&#x27;re writing an HTTP server we will typically allocate data for the request
headers and body. And once that request is handled, we de-allocate it and
allocate a new request. We can use our knowledge of our usage patterns to handle
allocations in a more targeted way. The way we do this is by obtaining a
relatively large-ish chunk of memory from our &lt;em&gt;system allocator&lt;&#x2F;em&gt;, and then using
that as the heap space for our custom allocator. These custom allocators are
also known as &lt;em&gt;&quot;region-based allocators&quot;&lt;&#x2F;em&gt; or &lt;em&gt;&quot;arena allocators&quot;&lt;&#x2F;em&gt;. Their key
benefit is that their memory management strategies are very simple, which can
make allocations so cheap they might as well be free.&lt;&#x2F;p&gt;
&lt;p&gt;There are many different types of arena allocators, but these are the ones I use
the most:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;slab allocators:&lt;&#x2F;strong&gt; For example the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;slab&#x2F;latest&#x2F;slab&#x2F;&quot;&gt;slab&lt;&#x2F;a&gt;
crate in Rust. This is ideal for when you perform many homogenous, short-lived
allocations over a longer period.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;bump allocators:&lt;&#x2F;strong&gt; For example the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;bumpalo&#x2F;latest&#x2F;bumpalo&#x2F;&quot;&gt;bumpalo&lt;&#x2F;a&gt; crate
in Rust. This is ideal for &lt;em&gt;phase-oriented allocations&lt;&#x2F;em&gt;, where you allocate a
number of heterogenous objects, say, on every iteration of a loop and then
de-allocate them at the end of it.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;While not every crate lends itself equally well to it, it&#x27;s even possible to
combine arena allocators to further customize allocation behavior.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;nesting-allocators&quot;&gt;Nesting Allocators&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;bumpalo&#x2F;latest&#x2F;bumpalo&#x2F;&quot;&gt;bumpalo&lt;&#x2F;a&gt; crate comes with an optional &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;bumpalo&#x2F;latest&#x2F;bumpalo&#x2F;collections&#x2F;index.html&quot;&gt;&lt;code&gt;collections&lt;&#x2F;code&gt;
feature&lt;&#x2F;a&gt; which
can be enabled to grant access to &lt;code&gt;String&lt;&#x2F;code&gt; and &lt;code&gt;Vec&lt;&#x2F;code&gt; types which are identical
to the stdlib&#x27;s versions other than the fact that they allocate on the bump
allocator. Using it looks like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;bumpalo::{Bump, collections::Vec};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = Bump::new();                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create a new bump allocator
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; v: Vec&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; = Vec::new_in(&amp;amp;b);   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Allocate on the bump allocator
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is an example of &lt;em&gt;nesting allocators&lt;&#x2F;em&gt;. The system allocator hosts the
bump allocator, and the bump allocator in turn hosts the vector. The main
downside of this is that we&#x27;re not using &lt;code&gt;std::vec::Vec&lt;&#x2F;code&gt;, but have to use
bumpalo&#x27;s custom vec implementation. That&#x27;s not ideal, not just because we now
have a second &lt;code&gt;Vec&lt;&#x2F;code&gt; type, but because we also don&#x27;t have other collection types
such as &lt;code&gt;HashMap&lt;&#x2F;code&gt;, &lt;code&gt;HashSet&lt;&#x2F;code&gt;, and every other type out there on crates.io.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;passing-allocators&quot;&gt;Passing Allocators&lt;&#x2F;h2&gt;
&lt;p&gt;The plan is to solve this limitation via the nightly &lt;code&gt;allocator_api&lt;&#x2F;code&gt; feature in
the stdlib. This extends the stdlib with methods such as
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;vec&#x2F;struct.Vec.html#method.new_in&quot;&gt;&lt;code&gt;Vec::new_in&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
which can take a custom
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;alloc&#x2F;trait.Allocator.html&quot;&gt;&lt;code&gt;Allocator&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; argument
to host the allocations in. I don&#x27;t have any particular opinions about the exact
&lt;code&gt;Allocator&lt;&#x2F;code&gt; trait, but I do have opinions about the way this bubbles up to
collection types.&lt;&#x2F;p&gt;
&lt;p&gt;Roughly speaking, the current design adds a new allocator generic param to
collection types which defaults to the global allocator (&lt;code&gt;Vec&amp;lt;T, A = GlobalAllocator&amp;gt;&lt;&#x2F;code&gt;). In order to uniformly make use of this, every constructor
method for every collection type needs to provide new &lt;code&gt;_in&lt;&#x2F;code&gt; variants of their
existing collections. At first that seems reasonable; but it quickly runs into
issues.&lt;&#x2F;p&gt;
&lt;p&gt;The first issue is usage with macros, which we can probably overcome. Macros
like &lt;code&gt;vec!&lt;&#x2F;code&gt; perform allocations, and in order to work with custom allocators
they should probably take an optional third param for the allocator. The second
issue is a lot harder: traits can&#x27;t take extra arguments. For example, if you
have an &lt;code&gt;&amp;amp;str&lt;&#x2F;code&gt;, and you want to convert it to &lt;code&gt;String&lt;&#x2F;code&gt; but use a bump allocator
you can&#x27;t keep using the existing &lt;code&gt;into&lt;&#x2F;code&gt; method. And because the &lt;code&gt;into&lt;&#x2F;code&gt; trait is
part of &lt;code&gt;core&lt;&#x2F;code&gt;, we can&#x27;t just add a new &lt;code&gt;into_in&lt;&#x2F;code&gt; method to the &lt;code&gt;Into&lt;&#x2F;code&gt; trait
either. The only real option is probably a new trait in &lt;code&gt;alloc&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; s = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_owned&lt;&#x2F;span&gt;&lt;span&gt;();         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 1. Uses the global allocator
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; bump = Bump::new();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; s = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_owned_in&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;bump); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 2. Uses a bump allocator
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; s: String = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;();     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 1. Always uses the global allocator
&lt;&#x2F;span&gt;&lt;span&gt;                                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 2. ❌ Unclear how to create a variant
&lt;&#x2F;span&gt;&lt;span&gt;                                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;    of this with a custom allocator
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While the number of collection types and constructor methods are limited, things
can quickly spiral out of hand when we factor in &lt;em&gt;composition&lt;&#x2F;em&gt;. In order for
things to work uniformly across the ecosystem, every type which holds a &lt;code&gt;Vec&lt;&#x2F;code&gt;
internally would need a second &lt;code&gt;_in&lt;&#x2F;code&gt; variant for all of their constructors and
conversions. That kind of duplication is uncompelling, meaning it&#x27;s likely we&#x27;re
only going to see &lt;em&gt;some&lt;&#x2F;em&gt; types adopt support for custom allocation while the
majority doesn&#x27;t. Not unlike how &lt;code&gt;#[no_std]&lt;&#x2F;code&gt; is not uniformly supported
throughout the crates ecosystem today.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;scoped-allocators&quot;&gt;Scoped Allocators&lt;&#x2F;h2&gt;
&lt;p&gt;What we&#x27;re really struggling with is that the global allocator acts, in a
capability-sense, as an &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&#x2F;ambient-authority&quot;&gt;ambient
authority&lt;&#x2F;a&gt;. Which is to say:
every function in Rust has access to the global allocator without functions
needing to take allocators explicitly as arguments. The allocator is just always
present. Except when we&#x27;re in &lt;code&gt;#[no_std]&lt;&#x2F;code&gt; environments, where there is no
allocator. Or when we&#x27;re trying to change which allocator we&#x27;re trying to take.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;_in&lt;&#x2F;code&gt; family of methods is an attempt to remedy the issue of having an ambient
allocator. But that has some drawbacks: most notably the bifurcation of APIs.
But also: it seems like that would be quite annoying to use. Manually having to
pass some form of &lt;code&gt;alloc&lt;&#x2F;code&gt; argument down to every function call doesn&#x27;t exactly
seem ideal.&lt;&#x2F;p&gt;
&lt;p&gt;Instead &lt;a href=&quot;https:&#x2F;&#x2F;tmandry.gitlab.io&#x2F;blog&#x2F;posts&#x2F;2021-12-21-context-capabilities&#x2F;&quot;&gt;Tmandry&#x27;s capabilities design&lt;&#x2F;a&gt; seems like a much more pleasant direction.
It acknowledges the existence of ambient capabilities, and instead just asks
that we express them at the signature level. Because they effectively function
as implicits, they just carry through to all argument in scope which need them:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; s = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_owned&lt;&#x2F;span&gt;&lt;span&gt;();             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 1. Uses the global allocator
&lt;&#x2F;span&gt;&lt;span&gt;with alloc = Bump::new() {              
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; s = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_owned_in&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;bump); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 2. Uses a bump allocator
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; s: String = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;();  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 1. Always uses the global allocator
&lt;&#x2F;span&gt;&lt;span&gt;with alloc = Bump::new() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; s = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.into;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 2. ✅ Uses a bump allocator       
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Compositions with functions and types would no longer require manually passing
allocators into arguments, but merely acknowledging the existence of an
allocator in the first place. That would mean we don&#x27;t have to provide new &lt;code&gt;_in&lt;&#x2F;code&gt;
methods which take allocators, but instead we could keep using the existing
&lt;code&gt;new&lt;&#x2F;code&gt; methods with some minor modifications.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Vec&amp;#39;s design on nightly today, providing both `new` and `new_in` methods
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Vec&amp;lt;T, A = Global&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ ...  }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Vec&amp;lt;T, A&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new_in&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;alloc&lt;&#x2F;span&gt;&lt;span&gt;: A) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ ...  }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; A design of vec using capabilities, using just a single `new` method.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Vec&amp;lt;T&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;with alloc = Global,
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Obviously questions remain about how to exactly model capabilities. Many types
in the stdlib liberally make use of ambient capabilities (e.g. allocation,
filesystem, networking, etc.) which we&#x27;d need to continue allowing to work as it
does today. But there is a question about how we can instead weave through
user-provided capabilities through the entire stdlib and crates.io ecosystem.
The answer requires having a way to continue relying on ambient capabilities,
but opt-out if you want to. Which is not entirely unlike &lt;code&gt;const&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The final benefit to this is that this would solve one of the current blockers
we have for string-literals. The obvious design for that would be to allow the
&lt;code&gt;s&lt;&#x2F;code&gt; prefix on literals to create allocated strings. But because that would act
as a language built-in, there is an open question on how to make that work with
custom allocators. Using capabilities would provide a compelling solution for that:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Rust today
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; s = String::from(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Chashu&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; With an `s` prefix, allocating on the global allocator
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; s = s&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Chashu&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; With an `s` prefix, allocating on a local allocator
&lt;&#x2F;span&gt;&lt;span&gt;with alloc = Bump::new() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; s = s&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Chashu&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we took a look at general allocation strategies, how allocations
can be nested today, which problems that approach has, and how we could simplify
that via the novel contexts&#x2F;capabilities language-feature. The design of
contexts&#x2F;capabilities is incomplete, so we intentionally didn&#x27;t go too deep into
that. Instead we only touched on the top-level semantics, showing specifically
how it could be leveraged to overcome some of the problems we have with
allocation today.&lt;&#x2F;p&gt;
&lt;p&gt;Fundamentally capabilities don&#x27;t provide anything &lt;em&gt;new&lt;&#x2F;em&gt;; they&#x27;re just a fancy
way of passing arguments to functions. But I also believe that is their
strength. It is &lt;em&gt;just passing arguments to functions&lt;&#x2F;em&gt;. But with significantly
less code to write, no method duplication, the ability to play along with trait
impls, and a lot more clarity of &lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;no-ghosts&#x2F;&quot;&gt;what your function needs to function&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t just think that capabilities could simplify the problem space for
allocators in Rust. I actually believe that it could be the canonical way in
which we solve the current &lt;code&gt;core&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;alloc&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;std&lt;&#x2F;code&gt; split in Rust. The &lt;code&gt;core&lt;&#x2F;code&gt;
library really is just &lt;code&gt;std&lt;&#x2F;code&gt; minus everything which relies on ambient
capabilities. If we could opt-out of relying on ambient capabilities in &lt;code&gt;std&lt;&#x2F;code&gt;,
the reason to have separate &lt;code&gt;core&lt;&#x2F;code&gt;, &lt;code&gt;alloc&lt;&#x2F;code&gt;, and &lt;code&gt;std&lt;&#x2F;code&gt; libraries should go away.&lt;&#x2F;p&gt;
&lt;p&gt;The other thought I want to share is that I believe capabilities such as
allocators are inherently &lt;em&gt;tree-structured&lt;&#x2F;em&gt;. I&#x27;ve recently written about
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;tree-structured-concurrency&#x2F;&quot;&gt;tree-structured
concurrency&lt;&#x2F;a&gt;
explaining how concurrency is best thought of as a tree. But from the
operational semantics side of the language we now
&lt;a href=&quot;https:&#x2F;&#x2F;www.ralfj.de&#x2F;blog&#x2F;2023&#x2F;06&#x2F;02&#x2F;tree-borrows.html&quot;&gt;tree-borrows&lt;&#x2F;a&gt; as well.
I feel like at a high-level thinking about program execution as a tree is
accurate, and we should be thinking of (nesting) capabilities such as allocators
as trees as well.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Totality</title>
            <pubDate>Thu, 20 Jul 2023 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/totality/</link>
            <guid>https://blog.yoshuawuyts.com/totality/</guid>
            <description>&lt;p&gt;Recently &lt;a href=&quot;https:&#x2F;&#x2F;theincredibleholk.org&quot;&gt;Eric&lt;&#x2F;a&gt; and I have been chatting with &lt;a href=&quot;https:&#x2F;&#x2F;www.microsoft.com&#x2F;en-us&#x2F;research&#x2F;people&#x2F;daan&#x2F;&quot;&gt;Daan
Leijen&lt;&#x2F;a&gt;, of
&lt;a href=&quot;https:&#x2F;&#x2F;koka-lang.github.io&#x2F;koka&#x2F;doc&#x2F;book.html&quot;&gt;Koka&lt;&#x2F;a&gt; fame, discussing among
other things the distribution of effects. Daan estimated that for a typical
program written in Koka the distribution of effects would roughly be something
like:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;~70% of a program could be &quot;total&quot; (as in: has no effects)&lt;&#x2F;li&gt;
&lt;li&gt;~15% of a program would have to deal with exceptions or divergence (may error,
may panic, or may loop indefinitely)&lt;&#x2F;li&gt;
&lt;li&gt;~5% of a program ends up dealing directly with IO resources&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That leaves another ~10% for wiggle room and other effects. And I think the
broad implications of this are &lt;em&gt;fascinating&lt;&#x2F;em&gt;. At least for Koka, according to
Daan the vast majority of code could be written as entirely un-effectful. No
panics, no infinite loops, no IO - just functions operating on input and
producing output.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;total-functions&quot;&gt;total functions&lt;&#x2F;h2&gt;
&lt;p&gt;Perhaps you may have heard people refer to Haskell as a &quot;pure&quot; language.
Functions in Haskell may by default diverge (loop infinitely), and they may
throw exceptions. Koka on the contrary is what you could call a &quot;total
language&quot;. By default functions are considered &quot;&lt;em&gt;total&lt;&#x2F;em&gt;&quot; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#math&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, and are
only allowed to operate on their inputs, and produce outputs. In Koka if you
want to write a &quot;pure&quot; function, you write a function which makes use of the
&lt;code&gt;exn&lt;&#x2F;code&gt; effect (&lt;em&gt;&quot;may throw exceptions&quot;&lt;&#x2F;em&gt;) and &lt;code&gt;div&lt;&#x2F;code&gt; effect (&lt;em&gt;&quot;may diverge&quot;&lt;&#x2F;em&gt;):&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;math&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;I believe terminology here is plucked from math&#x2F;category theory, which
I know little about - so I hope I&#x27;m doing this description justice.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Has no side-effects (&amp;quot;total&amp;quot;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fun &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;square_total&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;): &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;total int &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x &lt;&#x2F;span&gt;&lt;span&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Doesn&amp;#39;t terminate + throws exceptions (&amp;quot;pure&amp;quot;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; &amp;quot;pure&amp;quot; is an alias for the `&amp;lt;div,exn&amp;gt;` effects
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fun &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;square_pure&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;): &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;pure int &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;throw&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;oops&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x &lt;&#x2F;span&gt;&lt;span&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;square_pure&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In Rust however, we can&#x27;t write &lt;em&gt;total&lt;&#x2F;em&gt; functions. While we are able to write
functions which meet all the conditions to be &lt;em&gt;total&lt;&#x2F;em&gt; - we can&#x27;t actually
express in the type system that they&#x27;re total. Meaning that by reading a
function signature you have no idea whether a function will terminate, may
panic, or perhaps open files - it doesn&#x27;t say.&lt;&#x2F;p&gt;
&lt;p&gt;We get pretty close to the &quot;pure&quot; set of effects through the &lt;code&gt;const fn&lt;&#x2F;code&gt;
notation. It can&#x27;t heap-allocate, it can&#x27;t access IO, and can&#x27;t access globals
(&quot;statics&quot;). Right now it&#x27;s also &lt;em&gt;deterministic&lt;&#x2F;em&gt; - in Koka if code wants to be
nondeterministic it needs to be marked as
&lt;a href=&quot;https:&#x2F;&#x2F;koka-lang.github.io&#x2F;koka&#x2F;doc&#x2F;book.html#why-effects&quot;&gt;&lt;code&gt;ndet&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.  But in
order to declare &quot;total&quot; functions, we&#x27;d need to be able to strip the set
effects on functions further in Rust beyond what &lt;code&gt;const fn&lt;&#x2F;code&gt; does:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The ability to declare functions which will not panic&lt;&#x2F;li&gt;
&lt;li&gt;The ability to declare function which &quot;will not diverge&quot; (guarantee termination)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;So let&#x27;s take a look at what that means, and what it would take to implement in Rust.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;functions-which-cannot-panic&quot;&gt;Functions which cannot panic&lt;&#x2F;h2&gt;
&lt;p&gt;Rust distinguishes between &quot;panic&quot; for programmer-errors and &quot;result&quot; for
runtime-errors. Both can be mapped into each other using a combination of:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;result&lt;&#x2F;th&gt;&lt;th&gt;panic&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Create&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;return Err(..)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;panic&#x2F;fn.panic_any.html&quot;&gt;&lt;code&gt;panic_any&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; &#x2F; &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;result&#x2F;enum.Result.html#method.unwrap&quot;&gt;&lt;code&gt;unwrap&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Consume&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;match {}&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;panic&#x2F;fn.catch_unwind.html&quot;&gt;&lt;code&gt;catch_unwind&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;However, despite it being possible to convert between panics and errors - panics
themselves do not exist anywhere in the Rust type system. You cannot construct a
panic type and pass it around, you can only trigger a panic in-place. Similarly
functions don&#x27;t return a &lt;code&gt;Panic&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; or &lt;code&gt;impl Panic&lt;&#x2F;code&gt; when they can panic. Every
function can panic, and the ability to panic lives outside of the type system. &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#bad&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;bad&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;I don&#x27;t think it&#x27;s necessarily bad that panics live outside of the type
system though. I&#x27;m definitely not convinced that we should bring it into the
type system? Maybe it&#x27;s closer to &lt;code&gt;const&lt;&#x2F;code&gt; in the way that it just annotates the
function, but it doesn&#x27;t live &lt;em&gt;in&lt;&#x2F;em&gt; the type system? idk.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&quot;But Yosh?&quot;, I hear you asking, &quot;Do people even &lt;em&gt;want&lt;&#x2F;em&gt; to write functions which
can&#x27;t panic?&quot; And well dear reader, people certainly want to be able to do that.
There&#x27;s a thread full of people
&lt;a href=&quot;https:&#x2F;&#x2F;internals.rust-lang.org&#x2F;t&#x2F;enforcing-no-std-and-no-panic-during-build&#x2F;14505&#x2F;3&quot;&gt;here&lt;&#x2F;a&gt;
discussing wanting the ability to opt-out of panics. For reasons such as better
FFI (unwinding through FFI boundaries is generally unsound in Rust), support for
embedded systems, and more. Formal verification tools such as
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;viperproject&#x2F;prusti-dev&quot;&gt;Prusti&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;model-checking&#x2F;kani&quot;&gt;Kani&lt;&#x2F;a&gt; advertise their ability to prove
the absence of panics as their key features. And I know some folks working on
Windows here at Microsoft who would love it if we could prove that code which
should not panic in fact will never panic.&lt;&#x2F;p&gt;
&lt;p&gt;A basic form of &quot;will not panic&quot; notations can be implemented today via third
party crates such as Dtolnay&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dtolnay&#x2F;no-panic&quot;&gt;no-panic&lt;&#x2F;a&gt;,
and Japaric&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;japaric&#x2F;panic-never&quot;&gt;panic-never&lt;&#x2F;a&gt;. But while
it works okay, code like that is not composable and will eventually run into
&lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;inside-rust&#x2F;2022&#x2F;07&#x2F;27&#x2F;keyword-generics.html#a-taste-of-trouble-the-sandwich-problem&quot;&gt;the effect sandwich problem&lt;&#x2F;a&gt;.
Instead the better approach is probably to bring it into the type system, and
reason about it as an effect.&lt;&#x2F;p&gt;
&lt;p&gt;While a &quot;do not panic&quot; notation is sufficient to prove that a function won&#x27;t
panic, inside the function body we&#x27;re then obliged to actually write code which
won&#x27;t panic. And even with notations that&#x27;s hard because of a number of reasons:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;In Rust any operation may currently panic - opting into &quot;will not panic&quot;
semantics would be a pretty big shift.&lt;&#x2F;li&gt;
&lt;li&gt;Proving panic-freedom in a way that is also ergonomic requires introducing
verification tools into the language. &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;pattern-extensions&#x2F;#on-product-patterns&quot;&gt;Pattern
types&lt;&#x2F;a&gt;
backed by something like &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=2PEjvhkknzw&quot;&gt;Flux&lt;&#x2F;a&gt;
could be one approach. But this is an incredibly rich topic with lots of
challenges - many of which we don&#x27;t know if we can overcome.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In my post on &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;pattern-extensions&#x2F;#pattern-types&quot;&gt;pattern
types&lt;&#x2F;a&gt; I go into
this with some more detail on how we could deal with the first issue. Roughly
said: if we were able to encode more details about the types in the types
themselves, we could use that to prove to the compiler certain operations are
fine:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ❌ A basic doubling function in today&amp;#39;s Rust
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; combined with a &amp;quot;no_panic&amp;quot; notation
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Compiler error: this could panic because: u32::MAX + u32::MAX &amp;gt;= u32::MAX
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;no_panic&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;double&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;num&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    num + num
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ✅ A basic doubling function using a hypothetical &amp;quot;pattern type&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; notation combined with a &amp;quot;no_panic&amp;quot; notation
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; N: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MAX &lt;&#x2F;span&gt;&lt;span&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;no_panic&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;double&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;num&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;[0..N]) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MAX&lt;&#x2F;span&gt;&lt;span&gt;] {
&lt;&#x2F;span&gt;&lt;span&gt;    num + num
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;functions-which-guarantee-termination&quot;&gt;functions which guarantee termination&lt;&#x2F;h2&gt;
&lt;p&gt;In Rust by default functions do not guarantee termination. And that&#x27;s not a bad
property: we &lt;em&gt;want&lt;&#x2F;em&gt; to be able to write functions which don&#x27;t guarantee
termination, such as HTTP servers which keep listening indefinitely for
requests, or other similar &quot;main loops&quot;. Useful stuff.&lt;&#x2F;p&gt;
&lt;p&gt;But if every part of your program can loop indefinitely, it acts a little bit
like if any part of your program has access to raw pointers or IO: it can be
hard to track where exactly things are going wrong, because the potential site
of it is undetermined.&lt;&#x2F;p&gt;
&lt;p&gt;Just like with the hypothetical &quot;no_panic&quot; notation, we could have some form of
a &quot;nobody_loops&quot; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#everybody-loops&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; notation. This could signal to the compiler
that a function will guarantee termination, and that actions which don&#x27;t
terminate are disallowed. This one is &lt;del&gt;undecidedly hard&lt;&#x2F;del&gt; impossible to prove for
the general case, but if we wanted to do something practical we could probably
create a new unsafe marker trait like say &lt;code&gt;BoundedIterator&lt;&#x2F;code&gt; which would be
automatically implemented for things like looping over ranges, looping over
items in collections, etc.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;everybody-loops&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;pull&#x2F;19964&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;pull&#x2F;19964&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ✅ This would compile fine since the loop in the body has an upper bound
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;nobody_loops&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; n in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{n}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Similar to Rust&#x27;s borrow-checking rules, it&#x27;s unlikely any implementation for
&quot;will terminate&quot; will be enough to ever allow the full set of hypothetically
compliant programs.  That requires proving termination in the general case,
which I believe may be impossible. Instead the focus should be on a &lt;em&gt;practical&lt;&#x2F;em&gt;
subset of programs which can provably terminate. This is another potential
reason why generators as a first-class language feature would be useful. Because
the compiler generates the iterator implementation, it would enable creating
terminating iterators without manual unsafe trait impls:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Made-up syntax. This would return:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; -&amp;gt; impl Iterator&amp;lt;Item = Cat&amp;gt; + BoundedIterator
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;nobody_loops&lt;&#x2F;span&gt;&lt;span&gt;] gen &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;cats&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Cat { .. }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;const-functions&quot;&gt;Const Functions&lt;&#x2F;h2&gt;
&lt;p&gt;In Rust the &lt;code&gt;const&lt;&#x2F;code&gt; effect isn&#x27;t so much an effect onto itself, as it is the
subtraction of effects from the &quot;base&quot; set of effects. As we mentioned: const
functions must (currently) be deterministic, don&#x27;t get access to IO, don&#x27;t get
access to statics, and can&#x27;t allocate on the heap. And in return they gain the
ability to be evaluated during compilation.&lt;&#x2F;p&gt;
&lt;p&gt;But that&#x27;s if we view it from the perspective of Rust&#x27;s base set of effects. If
we look at const from a &quot;total&quot; perspective, then &quot;const&quot; represents roughly
represents the &quot;may panic&quot; and &quot;may diverge&quot; effects. And while we don&#x27;t have
any annotations for basic functions in Rust, they effectively act as a superset
of &quot;const&quot;, and also gain access to globals, the host environment (io), etc.&lt;&#x2F;p&gt;
&lt;p&gt;So if we take a position that const functions somehow subtract effects from
&quot;base Rust&quot;, then it is indeed the case that &quot;const&quot; can probably not be
considered an effect. But if we take a look at the effects from a perspective of
totality, then &quot;const&quot; and &quot;base&quot; contexts simply represent different sets of
effects:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;total&lt;&#x2F;strong&gt;: no effects&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;const&lt;&#x2F;strong&gt;: panic + diverge&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;base&lt;&#x2F;strong&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#base-rust&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;: panic + diverge + allocate + host environment + globals&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;base-rust&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;By &quot;base Rust&quot; I mean the capabilities a function has
when you write &lt;code&gt;fn foo&lt;&#x2F;code&gt; with no other annotations, compiled for a std-capable
target. It doesn&#x27;t have any specific effect annotations like &lt;code&gt;const&lt;&#x2F;code&gt; or &lt;code&gt;async&lt;&#x2F;code&gt;,
hence the &quot;base&quot; qualifier.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Reasoning about effects using a starting point of totality is also far simpler.
It might not necessarily map to the surface-level syntax Rust provides, but it
certainly makes it easier to reason about what happens when say, you have an
&lt;code&gt;unsafe const fn&lt;&#x2F;code&gt; compared to a &lt;code&gt;async gen fn&lt;&#x2F;code&gt; or something. Both have added
effects on top of &quot;total&quot;, but while they slightly overlap they also differ
somewhat. This makes it easier to reason about than when only talking about
effect in terms of subsets or supersets, rooted in &quot;base&quot; Rust.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;evolving-totality&quot;&gt;Evolving Totality&lt;&#x2F;h2&gt;
&lt;p&gt;So far we&#x27;ve mainly focused at the &quot;may panic&quot; and &quot;does not guarantee
termination&quot; effects. We&#x27;ve made the case that if only we had both those
effects, we&#x27;d achieve totality. But that&#x27;s not quite true. What &quot;total&quot; means
for a language will differ depending on the language. In a way you think of
&quot;total&quot; as the absence of all optional effects, but it includes all non-optional
assumptions.&lt;&#x2F;p&gt;
&lt;p&gt;Over time we can discover we want more control over which assumptions are baked
in and are optional. We&#x27;ve seen this with &quot;const rust&quot; already, which provides
fewer effects than &quot;base rust&quot; does. And both &quot;may panic&quot; and &quot;may diverge&quot; are
built-in assumptions which exist in Rust today, but could potentially be
surfaced. But those aren&#x27;t the only ones, there are potentially more such as:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;⚠️ Reader alert: I&#x27;m not proposing we add any of these effects. These are just
intended as illustrative examples for a point I&#x27;m working up towards the end of this
section. ⚠️&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Access to host environment&lt;&#x2F;strong&gt;: every function in Rust assumes it has access to a host
environment, and it can just call things like &lt;code&gt;File::open&lt;&#x2F;code&gt; to access resources
on the host. Embedded systems can&#x27;t assume a host. The difference between the
two is currently not encoded in the type system, and a notion of &quot;total&quot; may
want to do away with the assumption a host is present.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Drop is not guaranteed to be called&lt;&#x2F;strong&gt;: today any function in Rust can freely
take any type and pass it to &lt;code&gt;mem::forget&lt;&#x2F;code&gt; or similar to leak them without
calling their destructors. In a way you can think of every function having
access to a &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;linear-types-one-pager&#x2F;&quot;&gt;leak
effect&lt;&#x2F;a&gt;, and a notion of
&quot;total&quot; may want to exclude that.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Type conversions can be reversed&lt;&#x2F;strong&gt;: say a function takes an &lt;code&gt;impl Read&lt;&#x2F;code&gt;
argument, using the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;any&#x2F;trait.Any.html&quot;&gt;&lt;code&gt;Any&lt;&#x2F;code&gt;
trait&lt;&#x2F;a&gt; it&#x27;s possible to obtain
the underlying type, as long as the type name is accessible. This means there
is no guarantee that a function will only operate on the &lt;code&gt;impl Read&lt;&#x2F;code&gt;
interface, because it may in fact cast it back to the original type and
operate on that instead. Being able to obtain the underlying type could be
considered an effect which &quot;total&quot; may not want to have access to.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Type sizes can be accessed&lt;&#x2F;strong&gt;: every type has a size and a layout. Functions
can learn information about a type by calling the
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;mem&#x2F;fn.size_of.html&quot;&gt;size_of&lt;&#x2F;a&gt; function on a
type. A notation of totality could restrict obtaining any size or layout
information about a type.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Memory locations can be directly accessed&lt;&#x2F;strong&gt;: we assume types are backed by memory
addresses in the address space. This means we can always find the memory
address of a type. But what if we were to run, say, Rust on the JVM. The JVM
doesn&#x27;t expose an address space; it exposes objects and references. Which
means that &quot;type locations can be accessed&quot; could be considered an effect,
which could be absent from totality by default.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And there are probably lots more potential &quot;effects&quot; which fall outside of the
notion of &quot;totality&quot; presented in this post so far. That&#x27;s because in a way
writing effects brings the assumptions we make about functions directly into the
type system. And because our programs run on real physical hardware with memory
models and operating systems, it&#x27;s possible to map just about any detail of the
underlying hardware into an effect. Even to the point of silliness, such as
an effect which enables you to allocate stack space.&lt;&#x2F;p&gt;
&lt;p&gt;Choosing which effects to add means choosing which assumptions to surface. That
is a real art, and requires thinking through the purpose and use cases of the
effects. Ideally effects could even come in themes: for example &quot;type
conversions can be reversed&quot; and &quot;type sizes can be accessed&quot; share a theme of
&quot;type privacy&quot; - maybe they could be folded into each other. We&#x27;ve done
something similar with &quot;const&quot; too, where we&#x27;ve combined &quot;panic&quot; and &quot;diverge&quot;
into a single effect. What I&#x27;m trying to say is: what we mean by &quot;total&quot; depends
on our current idea of what the language is and should do. And it&#x27;s even
something which can change over time as our model and needs of the language
evolve.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Total functions go a step beyond &quot;pure&quot; functions because they also disallow
code from panicking and require functions provably terminate. Effect-wise it
represents the least a function could possibly do, so when talking about effects
we can think of every other effect as &quot;adding&quot; effects on top of the &quot;total&quot;
effect. This will also be helpful in case we ever manage to &lt;em&gt;constify&lt;&#x2F;em&gt; the
majority of the stdlib, and want to switch the default set of implied effects
across an edition bound. Reasoning about effects rooted in totality provides us
with a model to reason about what would change.&lt;&#x2F;p&gt;
&lt;p&gt;As we&#x27;re closing out here, something I did want to briefly touch on &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Rice%27s_theorem&quot;&gt;Rice&#x27;s
theorem&lt;&#x2F;a&gt;. It states that: &lt;em&gt;&quot;All
non-trivial semantic properties of programs are undecidable&quot;.&lt;&#x2F;em&gt; In effect what
we&#x27;re doing with effects is attempting to go against that. The &lt;code&gt;unsafe&lt;&#x2F;code&gt; keyword
in Rust exists because the compiler can&#x27;t prove memory safety for &lt;em&gt;all&lt;&#x2F;em&gt;
functions, just most of them but we need a way out for when we can&#x27;t. Similarly
we won&#x27;t be able to prove panic-freedom for all functions, or prove all
functions can terminate. But we can for a lot of functions; and statically
proving interesting properties of our programs is kind of what type systems are
about.&lt;&#x2F;p&gt;
&lt;p&gt;I find it fascinating that ~70% of code in a typical Koka program can be marked
as total. For Rust there is a thriving research movement to build verifiers for
the language, and one of the properties they often start by proving is
panic-freedom for functions. I can&#x27;t help but wonder how we could not just
expose these kinds of guarantees through extensions to Rust, but actually &lt;em&gt;by&lt;&#x2F;em&gt;
Rust itself. And I think in order to do that, we may want to start with by
adding ways to reason about semantic properties such as &quot;may panic&quot; or &quot;may
diverge&quot; as effects native to Rust.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;theincredibleholk.org&quot;&gt;Eric Holk&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;www.microsoft.com&#x2F;en-us&#x2F;research&#x2F;people&#x2F;daan&#x2F;&quot;&gt;Daan
Leijen&lt;&#x2F;a&gt; for reviewing
this post prior to publishing, and chatting about effects over the past few
months.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>bridging fuzzing and property testing</title>
            <pubDate>Mon, 10 Jul 2023 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/bridging-fuzzing-and-property-testing/</link>
            <guid>https://blog.yoshuawuyts.com/bridging-fuzzing-and-property-testing/</guid>
            <description>&lt;p&gt;It&#x27;s been over three years since Fitzgen published: &lt;a href=&quot;https:&#x2F;&#x2F;fitzgeraldnick.com&#x2F;2020&#x2F;01&#x2F;16&#x2F;better-support-for-fuzzing-structured-inputs-in-rust.html&quot;&gt;&lt;em&gt;&quot;Announcing Better Support
for Fuzzing with Structured Inputs in
Rust&quot;&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;,
and a little over two years since
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;arbitrary&#x2F;latest&#x2F;arbitrary&#x2F;&quot;&gt;arbitrary&lt;&#x2F;a&gt; 1.0 was released. A few years agoI
wrote a property-testing crate based on &lt;code&gt;arbitrary&lt;&#x2F;code&gt;, but never ended
up writing about it. So I wanted to take a moment to change that. We&#x27;ll start by
taking a look at automated testing, then cover the different approaches to it,
explain how to work with structured inputs, and finally introduce &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;heckcheck&#x2F;latest&#x2F;heckcheck&#x2F;&quot;&gt;heckcheck&lt;&#x2F;a&gt; -
a small property-testing library.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Update 2023-07-18:&lt;&#x2F;strong&gt; I recently learned about a different crate using a
similar approach to mine:
&lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;proptest-arbitrary-interop&quot;&gt;proptest-arbitrary-interop&lt;&#x2F;a&gt;.
The proptest crate is more mature than my &lt;code&gt;heckcheck&lt;&#x2F;code&gt; project, so if you&#x27;re
considering adopting the techniques described in this post - please check out
the proptest interop crate too.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fuzzing-vs-property-testing&quot;&gt;fuzzing vs property testing&lt;&#x2F;h2&gt;
&lt;p&gt;Both &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Fuzzing&quot;&gt;fuzzing&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Property_testing&quot;&gt;property
testing&lt;&#x2F;a&gt; are ways of
automatically testing code. Where unit tests typically test some expected set of
behavior, automated test have the ability to be more rigorous and exhaustive -
making them far more likely to weed out bugs - especially those you didn&#x27;t even
conceive of. Fuzzing and property testing have a lot in common with each other.
Where they tend to differ is how tests are driven.&lt;&#x2F;p&gt;
&lt;p&gt;With fuzzing you typically use some external agent to test your program. Fuzzers
usually have the ability to instrument the code under test, and make use of
tools such as
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Code_sanitizer#Other_sanitizers&quot;&gt;sanitizers&lt;&#x2F;a&gt; to
check whether invariants are violated. Fuzzers will also keep track of which
input leads to which branches being hit in code, tailor their input to cover as
many branches as possible. This process can take time, and is why it often pays
off to run fuzzers for extended periods of time or even
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;google&#x2F;oss-fuzz&quot;&gt;continuously&lt;&#x2F;a&gt;. In Rust support for fuzzing
is provided via the
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-fuzz&#x2F;cargo-fuzz&quot;&gt;&lt;code&gt;cargo-fuzz&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; extension.&lt;&#x2F;p&gt;
&lt;p&gt;Property testing typically works the other way around: property testing is
typically done by including a library in your test code which allows you to
drive the tests yourself. Rather than looking for crashes or sanitizer failures
the emphasis is more on checking your implementation using a strategy - more on
those in a later section. While fuzzing tends to be more thorough, property
testing tends to be faster to execute. Depending on what you&#x27;re testing it&#x27;s not
uncommon to integrate property tests in your CI test suite - and run them every
time you make a change. If you&#x27;re writing unsafe Rust you can even combine
property tests with &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&quot;&gt;miri&lt;&#x2F;a&gt; to validate with more confidence whether the runtime
behavior of your program matches Rust&#x27;s operational semantics.&lt;&#x2F;p&gt;
&lt;p&gt;The final piece of both property testing and fuzzing is that they perform
something called &lt;em&gt;test case shrinking&lt;&#x2F;em&gt; when they&#x27;re done. When they encounter a
failing test, what they&#x27;ll do is try and simplify the input to the bare minimum
to isolate the issue as much as possible. Once simplified it tends to be much
easier to understand, and in turn can become easier to &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;datrs&#x2F;memory-pager&#x2F;blob&#x2F;25c24144076ec6df46d0632c9e667df9582769c6&#x2F;tests&#x2F;regression.rs&quot;&gt;convert into unit
tests&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s a lot more to say about automated testing - including how to use it to
mess with the ordering of &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;loom&#x2F;latest&#x2F;loom&#x2F;&quot;&gt;concurrency primitives&lt;&#x2F;a&gt;, or to intentionally
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;turmoil&#x2F;latest&#x2F;turmoil&#x2F;&quot;&gt;mess with the network&lt;&#x2F;a&gt;. But roughly speaking that should all just be a
matter of wiring up drivers up to the same source of entropy coming from the
automated testing drivers.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;structured-inputs&quot;&gt;Structured Inputs&lt;&#x2F;h2&gt;
&lt;p&gt;In &lt;a href=&quot;https:&#x2F;&#x2F;fitzgeraldnick.com&#x2F;2020&#x2F;01&#x2F;16&#x2F;better-support-for-fuzzing-structured-inputs-in-rust.html&quot;&gt;Fitzgen&#x27;s
post&lt;&#x2F;a&gt;
he shows how it&#x27;s possible to combine fuzing with structured inputs using
&lt;code&gt;arbitrary&lt;&#x2F;code&gt; crate. The way a fuzzer typically works is that it generates random
data which is passed to a program over some channel. Sometimes this data is
generated from some corpus of data to try and weave in phrases we know the
program might be looking for - such as &lt;code&gt;HTTP&#x2F;1.1&lt;&#x2F;code&gt; or &lt;code&gt;GET&lt;&#x2F;code&gt; for an HTTP parser.
But with &lt;code&gt;arbitrary&lt;&#x2F;code&gt; this randomness can be more clearly channeled: it can take
the arbitrary stream of data, and use it to create structured types.&lt;&#x2F;p&gt;
&lt;p&gt;Part of the reason why Fitzgen did this work was to fuzz WASM programs. In
&lt;a href=&quot;https:&#x2F;&#x2F;fitzgeraldnick.com&#x2F;2020&#x2F;08&#x2F;24&#x2F;writing-a-test-case-generator.html&quot;&gt;&lt;em&gt;&quot;Writing a Test Case Generator for a Programming
Language&quot;&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;
he describes how using &lt;code&gt;cargo fuzz&lt;&#x2F;code&gt; and &lt;code&gt;arbitrary&lt;&#x2F;code&gt; he&#x27;s able to generate
endless amounts of new, valid WASM programs to pass to be used &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytecodealliance&quot;&gt;to test all
sorts of WASM-related tools&lt;&#x2F;a&gt;. This allows
far more code to be exercised than solely using a corpus-based approach ever
could.&lt;&#x2F;p&gt;
&lt;p&gt;To show an example of what it looks like to use cargo-fuzz, we can re-use the
RGB parser&#x2F;encoder example from Fitzgen&#x27;s blog - but with the actual methods
implemented. We start by defining a struct which takes red, green, and blue
values:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;arbitrary::Arbitrary;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A color value encoded as Red-Green-Blue
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Arbitrary, Debug, PartialEq, Eq)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Rgb {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;g&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Rgb {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Convert from RGB to Hexadecimal.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;to_hex&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; String {
&lt;&#x2F;span&gt;&lt;span&gt;        format!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{:02X}{:02X}{:02X}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.r, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.g, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.b)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Convert from Hexadecimal to RGB.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;from_hex&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;: String) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; s = s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;strip_prefix&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        Rgb {
&lt;&#x2F;span&gt;&lt;span&gt;            r: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;::from_str_radix(&amp;amp;s[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;            g: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;::from_str_radix(&amp;amp;s[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;            b: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;::from_str_radix(&amp;amp;s[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can expose this to &lt;code&gt;cargo-fuzz&lt;&#x2F;code&gt; to perform a roundtrip-test by creating a new
file containing the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The fuzz target takes a well-formed `Rgb` as input!
&lt;&#x2F;span&gt;&lt;span&gt;libfuzzer_sys::fuzz_target!(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;rgb&lt;&#x2F;span&gt;&lt;span&gt;: Rgb| {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; hsl = rgb.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_hsl&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; rgb2 = hsl.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_rgb&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; RGB -&amp;gt; HSL -&amp;gt; RGB is the identity function. This
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; property should hold true for all RGB colors!
&lt;&#x2F;span&gt;&lt;span&gt;    assert_eq!(rgb, rgb2);
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can then execute it using &lt;code&gt;cargo fuzz&lt;&#x2F;code&gt; by running:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; cargo fuzz run my_test
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;heckcheck-property-testing-using-arbitrary&quot;&gt;Heckcheck: Property Testing using Arbitrary&lt;&#x2F;h2&gt;
&lt;p&gt;As we&#x27;ve covered the &lt;code&gt;arbitrary&lt;&#x2F;code&gt; crate works great when fuzzing. And because
fuzzing and property testing are very similar, you&#x27;d assume that it should be
possible to use &lt;code&gt;arbitrary&lt;&#x2F;code&gt; for property-based tests too right? I couldn&#x27;t find
a crate which did this, so I ended up writing one! Enter
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;heckcheck&#x2F;latest&#x2F;heckcheck&#x2F;&quot;&gt;heckcheck&lt;&#x2F;a&gt;, a really small property-testing library. If we take our earlier RGB
example and adapt it to use heckcheck, it will look something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Validate values can be converted from RGB to Hex and back.
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;test&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;rgb_roundtrip&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    heckcheck::check(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;rgb&lt;&#x2F;span&gt;&lt;span&gt;: Rgb| {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; hex = rgb.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_hex&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = Rgb::from_hex(hex);
&lt;&#x2F;span&gt;&lt;span&gt;        assert_eq!(rgb, res);
&lt;&#x2F;span&gt;&lt;span&gt;        Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;    });
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And that&#x27;s all we had to do. To test the code we just run &lt;code&gt;cargo test&lt;&#x2F;code&gt; as
usual:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; cargo test
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The same code we would&#x27;ve written to interact with a fuzzer can now be
used for property testing too. As I&#x27;ve said earlier: both fuzzing and property
testing have more in common than not. The difference here compared to using a
fuzzer is that this can be run as part of CI without a problem, executes really
quickly, and is entirely portable. Fuzzers need to be installed on the system
first, typically execute more slowly, and some platforms such as Windows have
limited support for fuzzers.&lt;&#x2F;p&gt;
&lt;p&gt;I wrote &lt;code&gt;heckcheck&lt;&#x2F;code&gt; mostly to see whether it would be possible to write - and
the implementation is maybe ~400 lines or so in total. I bet it could be
improved, since in particular our shrinking code is less than ideal, while &lt;a href=&quot;https:&#x2F;&#x2F;link.springer.com&#x2F;chapter&#x2F;10.1007&#x2F;978-3-030-16722-6_24&quot;&gt;good
approaches are
known&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Compared to other popular property testing libraries &lt;code&gt;heckcheck&lt;&#x2F;code&gt; is more similar
to &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;quickcheck&#x2F;latest&#x2F;quickcheck&#x2F;&quot;&gt;&lt;code&gt;quickcheck&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; than it is to &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;proptest&#x2F;latest&#x2F;proptest&#x2F;index.html&quot;&gt;&lt;code&gt;proptest&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. It has a simple interface, can
generate complex values quickly, and uses external shrinking strategies. The
&lt;a href=&quot;https:&#x2F;&#x2F;proptest-rs.github.io&#x2F;proptest&#x2F;proptest&#x2F;vs-quickcheck.html&quot;&gt;proptest
docs&lt;&#x2F;a&gt;
contain a comparison between proptest and quickcheck, and that same comparison
could probably apply between proptest and heckcheck. The only place where the
comparison may differ is that the &lt;code&gt;arbitrary&lt;&#x2F;code&gt; crate has support for customizing
generated values. Say we wanted to restrict the values generated in our RGB
implementation to only valid RGB values, we could change the implementation to
the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;arbitrary::{Arbitrary, Unstructured};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A color value encoded as Red-Green-Blue
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Arbitrary, Debug, PartialEq, Eq)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Rgb {
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;arbitrary&lt;&#x2F;span&gt;&lt;span&gt;(with = color_range)]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;arbitrary&lt;&#x2F;span&gt;&lt;span&gt;(with = color_range)]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;g&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;arbitrary&lt;&#x2F;span&gt;&lt;span&gt;(with = color_range)]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Generate a valid RGB color value
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;color_range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;u&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; Unstructured) -&amp;gt; arbitrary::Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    u.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;int_in_range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;255&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If I could change one thing about the &lt;code&gt;arbitrary&lt;&#x2F;code&gt; crate it&#x27;s that I&#x27;d like to
see it support pattern-type notation inside the attributes. Patterns allow
primitive values to be restricted to a subset of their possible inputs, which
should be a fairly common use. With that we could imagine the RGB type could
instead be written like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! ⚠️ This is purely speculative and not currently supported ⚠️
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;arbitrary::{Arbitrary, Unstructured};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A color value encoded as Red-Green-Blue
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Arbitrary, Debug, PartialEq, Eq)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Rgb {
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;arbitrary&lt;&#x2F;span&gt;&lt;span&gt;(pattern = 0..=255)]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;arbitrary&lt;&#x2F;span&gt;&lt;span&gt;(pattern = 0..=255)]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;g&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;arbitrary&lt;&#x2F;span&gt;&lt;span&gt;(pattern = 0..=255)]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;automated-testing-strategies&quot;&gt;Automated testing strategies&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we&#x27;ve covered what the different ways of automated testing are, it&#x27;s
worth briefly touching on some common testing strategies. Because once you&#x27;ve
understood that automated testing might be good, there often is a bit of a gap
to actually implement it in your own code. And that&#x27;s what testing strategies
are for. These are some common testing strategies:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;roundtrip testing&lt;&#x2F;strong&gt;: generate a message, pass it to the encoder, then pass
the encoder&#x27;s output to the decoder. The decoder&#x27;s output should be the same
as the original message.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;differential testing&lt;&#x2F;strong&gt;: test the program against a &quot;known good&quot;
implementation of a similar program (also known as an &quot;oracle&quot;). This is
useful if, for example, you&#x27;re re-implementing an existing protocol or algorithm.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;invariant testing&lt;&#x2F;strong&gt;: test that a certain property &lt;em&gt;always&lt;&#x2F;em&gt; holds. This can
be a universal property like: &quot;my program didn&#x27;t crash&quot;. But invariants can be
specific too. &lt;a href=&quot;https:&#x2F;&#x2F;hachyderm.io&#x2F;@rain&quot;&gt;Rain&lt;&#x2F;a&gt; recently gave a great example
that if you&#x27;re for example testing a sorting function, you can check its
correctness by making iterating over each number and checking it&#x27;s bigger than
the last number.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We&#x27;ve already covered roundtrip testing earlier in this post, and I believe
invariant testing should be fairly straight forward. So as we&#x27;re closing out
here I just briefly wanted to show an example of how to perform differential
testing using an approach &lt;a href=&quot;https:&#x2F;&#x2F;tylerneely.com&quot;&gt;Tyler Neely&lt;&#x2F;a&gt; introduced me to a few years ago.&lt;&#x2F;p&gt;
&lt;p&gt;The way this works is that you use your source of entropy to generate a sequence
of operations which you then apply to both your oracle and your program under
test. Should your test trigger a failure, the shrinker will kick in and try and
remove operations trying to uncover the minimal sequence of operations needed to
trigger the bug. Say we in the process of building the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;smallvec&#x2F;latest&#x2F;smallvec&#x2F;&quot;&gt;smallvec&lt;&#x2F;a&gt; crate; the
implementation differs from the stdlib, but the observable behavior should be
the same. Which means we can use the stdlib&#x27;s &lt;code&gt;Vec&lt;&#x2F;code&gt; as our oracle for the test,
which could look something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A single operation we can apply
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Arbitrary)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;Operation {
&lt;&#x2F;span&gt;&lt;span&gt;    Insert(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    Fetch(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;test&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;differential_smallvec_test&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    heckcheck::check(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;operations&lt;&#x2F;span&gt;&lt;span&gt;: Vec&amp;lt;Operation&amp;gt;| {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Setup both our subject and the oracle
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; subject = smallvec::SmallVec::new();
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; oracle = vec![];
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Apply the same operations in-order to both the subject and the oracle
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; comparing outputs whenever we get any.
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; operation in operations {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; operation {
&lt;&#x2F;span&gt;&lt;span&gt;                Insert(index, value) =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;                    oracle.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(index, value);
&lt;&#x2F;span&gt;&lt;span&gt;                    subject.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(index, value);
&lt;&#x2F;span&gt;&lt;span&gt;                }
&lt;&#x2F;span&gt;&lt;span&gt;                Fetch(index) =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;                    assert_eq!(oracle.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(index), subject.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(index));
&lt;&#x2F;span&gt;&lt;span&gt;                }
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    });
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve covered what fuzzing and property testing are, how they&#x27;re
similar, and how they differ. We&#x27;ve introduced &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;heckcheck&#x2F;latest&#x2F;heckcheck&#x2F;&quot;&gt;heckcheck&lt;&#x2F;a&gt;, a small
property-testing library and shown how you can use it to implement various
testing strategies with.&lt;&#x2F;p&gt;
&lt;p&gt;I believe one of the greatest strengths Rust has is its ability to provide
uniform experiences. And I believe that automated testing is one of the best
tools we have to ensure the correctness of the implementations of our Rust
programs. I&#x27;d love to one day see Rust provide facilities out of the box for
automated testing - including a standard &lt;code&gt;Arbitrary&lt;&#x2F;code&gt; interface.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Tree-Structured Concurrency</title>
            <pubDate>Sat, 01 Jul 2023 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/tree-structured-concurrency/</link>
            <guid>https://blog.yoshuawuyts.com/tree-structured-concurrency/</guid>
            <description>&lt;p&gt;For a while now I&#x27;ve been trying to find a good way to explain what structured
concurrency is, and how it applies to Rust. I&#x27;ve come up with zingers such as:
&lt;em&gt;&quot;Structured concurrency is structured programming as applied to concurrent
control-flow primitives&quot;&lt;&#x2F;em&gt;. But that requires me to start explaining what
structured programming is, and suddenly I find myself 2000 words deep into a
concept which seems natural to most people writing programs today &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#dijkstra&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Instead I want to try something different. In this post I want to provide you
with a practical introduction to structured concurrency. I will do my best to
explain what it is, why it&#x27;s relevant, and how you can start applying it to your
rust projects today. Structured concurrency is a lens I use in almost all of my
reasoning about async Rust, and I think it might help others too. So let&#x27;s dive in.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;This post assumes some familiarity with &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;why-async-rust&#x2F;&quot;&gt;async Rust&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-cancellation-1&#x2F;&quot;&gt;async cancellation&lt;&#x2F;a&gt;.
If you aren&#x27;t already, it might be helpful to skim through the earlier posts on
the topic.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;dijkstra&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;If you&#x27;re interested in structured programming though, I can
recommend &lt;a href=&quot;https:&#x2F;&#x2F;www.informatik.uni-bremen.de&#x2F;agbkb&#x2F;lehre&#x2F;programmiersprachen&#x2F;artikel&#x2F;EWD-notes-structured.pdf&quot;&gt;Dijkstra&#x27;s writing&lt;&#x2F;a&gt; on the subject. Most programming
languages we use today are structured, so reading about a time when when that
wasn&#x27;t the case is really interesting.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;what-is-structured-concurrency&quot;&gt;What is structured concurrency?&lt;&#x2F;h2&gt;
&lt;p&gt;Structured concurrency is a property of your program. It&#x27;s not just any
structure, the structure of the program is guaranteed to be a &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;graphs&#x2F;#trees&quot;&gt;tree&lt;&#x2F;a&gt; regardless
of how much concurrency is going on internally &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#academia&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. A good way to think
about it is that if you could plot the live call-graph of your program as a
series of relationships it would neatly form a tree. No cycles &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#recursion&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. No
dangling nodes. Just a single tree.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;academia&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;When I was researching this topic last year I found a paper from I
believe the 80&#x27;s which used the phrase &quot;tree-structured concurrency&quot;. I couldn&#x27;t
find it again in time for this post, but I remember tweeting about it because I
hadn&#x27;t seen the term before and I thought it was really helpful!&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;recursion&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Yes yes, recursion can make functions call themselves - or even
call themselves through a proxy. By &quot;live call-graph&quot; I mean it like how flame
charts visualize function calls. Recursion is visualized by stacking function
calls on top of each other. The same idea would apply here by adding new async nodes
as children of existing nodes. The emphasis here is very much on &lt;em&gt;live&lt;&#x2F;em&gt;
call-graph, not &lt;em&gt;logical&lt;&#x2F;em&gt; call-graph.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;figure&gt;
    &lt;img src=&quot;tree_plain.jpg&quot; alt=&quot;tree&quot;&gt;
    &lt;figcaption&gt;
        Fig 1. The arrows point from parent nodes to
        child nodes. It has no cycles. A parent can have multiple children. But
        a child always has a single parent - except for the root node.
    &lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;And this structure, at least in async Rust, provides three key properties:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cancellation propagation:&lt;&#x2F;strong&gt; When you drop a future to cancel it, it&#x27;s
guaranteed that all futures underneath it are also cancelled.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Error propagation:&lt;&#x2F;strong&gt; When an error is created somewhere down in the
call-graph, it can always be propagated up to the callers until there is a
caller who is ready to handle it.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Ordering of operations:&lt;&#x2F;strong&gt; When a function returns, you know it is done doing
work. No surprises that things are still happening long after you thought the
function had completed.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;These properties put together lead to something called a &lt;strong&gt;&quot;black box model of
execution&quot;&lt;&#x2F;strong&gt;: under a structured model of computing you don&#x27;t need to know
anything about the inner workings of the functions you&#x27;re calling, because their
behavior is guaranteed. A function will return when it&#x27;s done, will cancel all
work when you ask it to, and you&#x27;ll always receive an error if there is something
which needs handling. And as a result code under this model is &lt;strong&gt;composable&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;figure&gt;
    &lt;img src=&quot;tree_flow.jpg&quot; title=&quot;figure 2&quot; alt=&quot;tree&quot;&gt;
    &lt;figcaption&gt;
        Fig 2. Under structured concurrency every future has a parent,
        cancellation flows downward, and errors flow upward. When a future
        returns, you can be sure it&#x27;s done doing work. 
    &lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;If your model of concurrency is &lt;em&gt;unstructured&lt;&#x2F;em&gt;, then you don&#x27;t have these
guarantees. So in order to guarantee that say, cancellation is correctly
propagated, you&#x27;ll need to inspect the inner workings of every function you&#x27;re
calling. Code under this model is not composable, and requires manual checks and
bespoke solutions. This is both labor-intensive and prone to errors.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;unstructured-concurrency-an-example&quot;&gt;Unstructured concurrency: an example&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s start by implementing a classic concurrency pattern: &quot;race&quot;. But rather
than using &lt;em&gt;structured&lt;&#x2F;em&gt; primitives, we can use the staples of unstructured
programming: the venerable &lt;code&gt;task::spawn&lt;&#x2F;code&gt; and &lt;code&gt;channel&lt;&#x2F;code&gt;. The way &quot;race&quot; works is
it takes two futures, and we try and get the output of whichever one completes
first is whose message we read. We could write it something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::{channel, task};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(sender0, receiver) = channel::bounded(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; sender1 = sender0.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;task::spawn(async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 👈 Task &amp;quot;C&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    task::sleep(Duration::from_millis(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;    sender1.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;first&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await;
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;task::spawn(async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 👈 Task &amp;quot;B&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    task::sleep(Duration::from_millis(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;    sender0.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;second&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await;
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; msg = receiver.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;recv&lt;&#x2F;span&gt;&lt;span&gt;().await; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 👈 Future &amp;quot;A&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{msg}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While this implements &quot;race&quot; semantics correctly, it doesn&#x27;t handle
cancellation. If one of the branches completes, we&#x27;d ideally like to cancel the
other. And if the containing function is cancelled, both computations should be
cancelled. Because of how we&#x27;ve structured the program neither task is anchored
to a parent future, and so we can&#x27;t cancel either computation directly. Instead
the solution would be to come up with some design using more channels, anchor
the handles - or we could instead rewrite this using structured primitives.&lt;&#x2F;p&gt;
&lt;figure&gt;
    &lt;img src=&quot;race_tasks.jpg&quot; title=&quot;figure 3&quot; alt=&quot;tree&quot;&gt;
    &lt;figcaption&gt;
        Fig 3. You can create a &quot;race&quot; operation by combining tasks and channels. Data
        can flow out of the tasks to the caller. But because the tasks aren&#x27;t rooted
        in a parent task, cancellation doesn&#x27;t propagate.
    &lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;h2 id=&quot;structured-concurrency-an-example&quot;&gt;Structured concurrency: an example&lt;&#x2F;h2&gt;
&lt;p&gt;We can rewrite the example above using structured primitives instead. Rather
than DIY-ing our own &quot;race&quot; implementation using tasks and channels, we should
instead be using a &quot;race&quot; primitive which implements those semantics for us -
and correctly handles cancellation. Using the &lt;a href=&quot;http:&#x2F;&#x2F;docs.rs&#x2F;futures-concurrency&quot;&gt;futures-concurrency&lt;&#x2F;a&gt; library we
could do that as follows:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_concurrency::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::task;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = async {                   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 👈 Future &amp;quot;C&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    task::sleep(Duration::from_millis(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;first&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = async {                   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 👈 Future &amp;quot;B&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    task::sleep(Duration::from_millis(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;second&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; msg = (c, b).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;race&lt;&#x2F;span&gt;&lt;span&gt;().await;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 👈 Future &amp;quot;A&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{msg}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When one future completes here, the other future is cancelled. And should the
&lt;code&gt;Race&lt;&#x2F;code&gt; future be dropped, then both futures are cancelled. Both futures have a
parent future when executing. Cancellation propagates downwards. And while there
are no errors in this example, if we were working with fallible operations then
early returns would cause the future to complete early - and errors would be
handled as expected.&lt;&#x2F;p&gt;
&lt;figure&gt;
    &lt;img src=&quot;race_futures.jpg&quot; title=&quot;figure 4&quot; alt=&quot;tree&quot;&gt;
    &lt;figcaption&gt;
        Fig 4. By using a structured &quot;race&quot; primitive all child futures are rooted in
        a parent future. Which allows both cancellation and errors to propagate. And
        the operation won&#x27;t return until all child futures have dropped.
    &lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;So far we&#x27;ve looked at just the &quot;race&quot; operation, which encodes: &lt;em&gt;&quot;Wait for the
first future to complete, then cancel the other&quot;&lt;&#x2F;em&gt;. But other async concurrency
operations exist as well, such as:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;join&lt;&#x2F;strong&gt;: wait for all futures to complete.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;race_ok&lt;&#x2F;strong&gt;: wait for the first future to complete which returns &lt;code&gt;Ok&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;try_join&lt;&#x2F;strong&gt;: wait for all futures to complete, or return early if there is an error.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;merge&lt;&#x2F;strong&gt;: wait for all futures to complete, and yield items from a stream as
soon as they&#x27;re ready.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;There are a few more such as &quot;zip&quot;, &quot;unzip&quot;, and &quot;chain&quot; - as well as dynamic
concurrency primitives such as &quot;task group&quot;, &quot;fallible task group&quot;, and more.
The point is that the set of concurrency &lt;em&gt;primitives&lt;&#x2F;em&gt; is bounded. But they can
be recombined in ways that makes it possible express any form of concurrency you
want. Not unlike how if a programming language supports branching, loops, and
function calls you can encode just about any control-flow logic you want,-
without ever needing to use &quot;goto&quot;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-the-worst-that-can-happen&quot;&gt;What&#x27;s the worst that can happen?&lt;&#x2F;h2&gt;
&lt;p&gt;People sometimes ask: What&#x27;s the worst that can happen when you don&#x27;t have
structured concurrency? There are a number of bad outcomes possible, including
but not limited to: data loss, data corruption, and memory leaks.&lt;&#x2F;p&gt;
&lt;p&gt;While Rust guards against &lt;em&gt;data races&lt;&#x2F;em&gt; which fall under the category of &quot;memory
safety&quot;, Rust can&#x27;t protect you from logic bugs. For example: if you execute a
&lt;code&gt;write&lt;&#x2F;code&gt; operation inside of a task whose handle isn&#x27;t joined, then you&#x27;ll need
to find some alternate mechanism to guarantee the ordering of that operation in
relation to the rest of the program. If you get that wrong you might
accidentally write to a closed resource and lose data. Or perform an
out-of-order write, and accidentally corrupt a resource &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#sql&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. These kinds of bugs
are not in the same class as memory safety bugs. But they are nonetheless
serious, and they can be mitigated through principled API design.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;sql&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;At a previous job we experienced exactly this in a database client: we
were having issues propagating cancellation correctly, which meant that the
connection protocol could be corrupted because we didn&#x27;t flush messages when we
should have.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;applying-structured-concurrency-to-your-programs&quot;&gt;Applying structured concurrency to your programs&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;task::spawn&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;When using or authoring async APIs in Rust, you should ask yourself the following questions to ensure structured concurrency:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Cancellation propagation&lt;&#x2F;strong&gt;: If this future or function is dropped, will cancellation propagate to all child futures?&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Error propagation&lt;&#x2F;strong&gt;: If an error happens anywhere in this future, can we either handle it directly or surface it to the caller?&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Ordering of operations&lt;&#x2F;strong&gt;: When this function returns, will no more work continue to happen in the background?&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;If all of these properties are true, then once the function exits it&#x27;s done
executing and you&#x27;re good. This however leads us to a major issue in today&#x27;s
async ecosystem: neither async-std nor tokio provide a &lt;code&gt;spawn&lt;&#x2F;code&gt; function which is
structured.  If you drop a task handle the task isn&#x27;t cancelled, but instead it&#x27;s
detached and will continue to run in the background. This means that
cancellation doesn&#x27;t automatically propagate across task boundaries, causing it
to be unstructured.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;smol&#x2F;latest&#x2F;smol&#x2F;struct.Task.html&quot;&gt;smol&lt;&#x2F;a&gt; library gets closer
though. It has a task implementation which gets us closer to &quot;cancel on
drop&quot;-semantics out of the box. Though it doesn&#x27;t get us all the way yet because
it doesn&#x27;t guarantee an ordering of operations. When a smol &lt;code&gt;Task&lt;&#x2F;code&gt; is dropped
the task isn&#x27;t guaranteed to have been cancelled, all it guarantees is that the
task will be cancelled at some point in the future.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;async drop&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Which brings us to the biggest piece missing from async Rust&#x27;s structured
concurrency story: the lack of async Drop in the language. Smol&#x27;s
tasks have an async
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;smol&#x2F;latest&#x2F;smol&#x2F;struct.Task.html#method.cancel&quot;&gt;cancel&lt;&#x2F;a&gt; method
which only resolves once the task has successfully been cancelled. Ideally we
could call this method in the destructor and wait for it. But in order to do
that today we&#x27;d need to block the thread, and that can lead to throughput
issues. No, in practice what we really need for this to work well is async
destructors &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#flush&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;flush&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;Async cancellation is hardly the only motivation for async Drop. It
also prevents us from encoding basic things like: &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;latest&#x2F;async_std&#x2F;io&#x2F;struct.BufWriter.html&quot;&gt;&quot;flush this operation on
drop&quot;&lt;&#x2F;a&gt; -
which is something we &lt;em&gt;can&lt;&#x2F;em&gt; encode in non-async Rust today.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;strong&gt;what can you do today?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;But while we can&#x27;t yet trivially fulfill all requirements for async structured
concurrency for async tasks, not all hope is lost. Without async Drop we can
already achieve 2&#x2F;3 of the requirements for task spawning today. And if you&#x27;re
using a runtime other than smol, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yoshuawuyts&#x2F;tasky&#x2F;blob&#x2F;fb8a8e7040c7cd68a5e38b895bbd032ded578a3f&#x2F;src&#x2F;lib.rs#L41-L75&quot;&gt;adapting the spawn method&lt;&#x2F;a&gt; to work like
smol&#x27;s does is not too much work. But most concurrency doesn&#x27;t need tasks
because it isn&#x27;t dynamic. For that you can take a look at the
&lt;a href=&quot;http:&#x2F;&#x2F;docs.rs&#x2F;futures-concurrency&quot;&gt;futures-concurrency&lt;&#x2F;a&gt; library which implements composable primitives for
structured concurrency.&lt;&#x2F;p&gt;
&lt;p&gt;If you want to adopt structured concurrency in your codebase today, you can
start by adopting it for non-task-based concurrency. And for task-based
concurrency you can adopt the smol model of task spawning to benefit from most
of the benefits of structured concurrency today. And eventually the hope is we
can add some form of async Drop to the language to close out the remaining
holes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pattern-managed-background-tasks&quot;&gt;Pattern: managed background tasks&lt;&#x2F;h2&gt;
&lt;p&gt;People frequently ask how they can implement &quot;background tasks&quot; under structured
concurrency. This is used in scenarios such as an HTTP request handler which
also wants to submit a piece of telemetry. Rather than blocking sending the
response on the telemetry, it spawns a &quot;background task&quot; to submit the telemetry
in the background, and immediately returns from the request. This can look
something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; app = tide::new();
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;post&lt;&#x2F;span&gt;&lt;span&gt;(|_| async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    task::spawn(async {  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 👈 Spawns a background task…
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; _res = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send_telemetry&lt;&#x2F;span&gt;&lt;span&gt;(data, more_data).await;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; … what if `res` is an `Err`? How should we handle errors here?
&lt;&#x2F;span&gt;&lt;span&gt;    });
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello world&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 👈 …and returns immediately after.
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;listen&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The phrase &quot;background task&quot; seems polite and unobtrusive. But from a structured
perspective it represents a computation without a parent - it is a &lt;em&gt;dangling
task&lt;&#x2F;em&gt;. The core of the pattern we&#x27;re dealing with is that we want to create a
computation which outlives the lifetime of the request handler. We can resolve
this by rather than creating a dangling task to submit it to a task queue or
task group which outlives the request handler.
Unlike a dangling task, a &lt;em&gt;task queue&lt;&#x2F;em&gt; or &lt;em&gt;task group&lt;&#x2F;em&gt; preserves structured
concurrency. Where a dangling task doesn&#x27;t have a parent future and becomes
unreachable, using a task queue we transmit the ownership of a future to a
different object which outlives the current more ephemeral scope.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve heard people make the argument before that &lt;code&gt;task::spawn&lt;&#x2F;code&gt; is perfectly
structured, as long as you think of it as spawning on some sort of unreachable,
global task pool. But the question shouldn&#x27;t be whether tasks are spawned on a task
pool, but what the relationship is of those tasks to the rest of the program.
Because we cannot cancel and recreate an unreachable task pool. Nor can we
receive errors from this pool, or wait for all tasks in it to complete. It
doesn&#x27;t provide the properties we want from structured concurrency - so we
shouldn&#x27;t consider it structured.&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t feel like the ecosystem has any great solutions to this yet - in part
limited because we want &lt;a href=&quot;https:&#x2F;&#x2F;tmandry.gitlab.io&#x2F;blog&#x2F;posts&#x2F;2023-03-01-scoped-tasks&#x2F;&quot;&gt;&quot;scoped
tasks&quot;&lt;&#x2F;a&gt; which
basically require &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;linearity-and-control&#x2F;&quot;&gt;linear
destructors&lt;&#x2F;a&gt; to function.
But &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-task-group&#x2F;latest&#x2F;async_task_group&#x2F;&quot;&gt;other experiments
exist&lt;&#x2F;a&gt; so we can use
that plus channels to put something together which gives us what we want:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;⚠️ Note: This code is not considered &quot;good&quot; by the author, and is merely used as an
example to show that this is possible to write today. More design work is
necessary to make this ergonomic ⚠️&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create a channel to send and receive futures over.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(sender, receiver) = async_channel::unbounded();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create a structured task group at the top-level, next to the HTTP server
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; If any errors are returned by the spawned tasks, all active tasks are cancelled
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; and the error is returned by the handle.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; telemetry_handle = async_task_group::group(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;group&lt;&#x2F;span&gt;&lt;span&gt;| async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(telemetry_future) = receiver.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().await {
&lt;&#x2F;span&gt;&lt;span&gt;        group.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            telemetry_future.await?;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 👈 Propagate errors upwards
&lt;&#x2F;span&gt;&lt;span&gt;            Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;        });
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(group)
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create an application state for our HTTP server
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Clone)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;State {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;sender&lt;&#x2F;span&gt;&lt;span&gt;: async_channel::Sender&amp;lt;impl Future&amp;lt;Result&amp;lt;_&amp;gt;&amp;gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create the HTTP server
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; app = tide::new();
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;post&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;req&lt;&#x2F;span&gt;&lt;span&gt;: Request&amp;lt;State&amp;gt;| async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    state.sender.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(async {   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 👈 Sends a future to the handler loop…
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send_telemetry&lt;&#x2F;span&gt;&lt;span&gt;(data, more_data).await?;
&lt;&#x2F;span&gt;&lt;span&gt;        Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;    }).await;
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello world&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 👈 …and returns immediately after.
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Concurrently execute both the HTTP server and the telemetry handler,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; and if either one stops working the other stops too.
&lt;&#x2F;span&gt;&lt;span&gt;(app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;listen&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;), telemetry_handle).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;race&lt;&#x2F;span&gt;&lt;span&gt;().await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Like I said: we need to do a lot more API work to be able to rival the
convenience of just firing off a dangling task. But what we lack for in API
convenience, we make up for in semantics. Unlike our earlier example this will
correctly propagates cancellation and errors, and every executing future is
owned by a parent future. We could even take things a step further and implement
things like retry-handlers with error quotas on top of this to create a more
resilient system. But hopefully this is enough already to get the idea across of
what we could be doing with this.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;guaranteeing-structure&quot;&gt;Guaranteeing Structure&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;ve been asking myself for a while now: &lt;em&gt;&quot;Would it be possible for Rust to
enforce structured concurrency in the language and libraries?&quot;&lt;&#x2F;em&gt; I don&#x27;t believe
this is something we guarantee from the language. But it is something &lt;em&gt;can&lt;&#x2F;em&gt;
guarantee for Rust&#x27;s library code, and make it so most async code is structured
by default.&lt;&#x2F;p&gt;
&lt;p&gt;The reason why I don&#x27;t believe it&#x27;s fundamentally possible to guarantee
structure at the language level is because it&#x27;s possible to express any kind of
program in Rust, which includes unstructured programs. Futures, channels, and
tasks as they exist today are all just regular library types. If we wanted to
enforce structure from the language, we would need to find a way to disallow the
creation of these libraries - and that seems impossible for a general-purpose
language &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#structured-state-machine&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;structured-state-machine&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;An example of this from structured programming:
Rust is a structured language. Assembly is not a structured language. You can
implement an assembly interpreter entirely in safe Rust - meaning you can
express unstructured code in a structured language. I could show examples of
this, but eh I hope the general line of reasoning makes sense here.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Instead it seems more practical to me to adopt tree-structured concurrency as
the model we follow for async Rust. Not as a memory-safety guarantee, but as a
design discipline we apply across all of async Rust. APIs which are unstructured
should not be added to the stdlib. And our tooling should be aware that
unstructured code may exist, so it can flag it when it encounters it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post I&#x27;ve shown what (tree-)structured concurrency is, why it&#x27;s
important for correctness, and how you can apply it in your programs. I hope
that by defining structured concurrency in terms of guarantees about propagation
of errors and cancellation, we can create a practical model for people to
reason about async Rust with.&lt;&#x2F;p&gt;
&lt;p&gt;As &lt;a href=&quot;https:&#x2F;&#x2F;opensource.googleblog.com&#x2F;2023&#x2F;06&#x2F;rust-fact-vs-fiction-5-insights-from-googles-rust-journey-2022.html&quot;&gt;recently reported by
Google&lt;&#x2F;a&gt;,
async Rust is one of the most difficult aspects of Rust to learn. It seems
likely that the lack of structure in async Rust code today did not help. In
async code today neither cancellation nor errors are guaranteed to propagate.
This means that if you want to reliably compose code, you need to have knowledge
of the inner workings of the code you&#x27;re using. By adopting a (tree-)structured
model of concurrency these properties can instead be guaranteed from the outset,
which in turn would make Async Rust easier to reason about and teach. Because
&lt;em&gt;&quot;If it compiles it works&quot;&lt;&#x2F;em&gt; should apply to async Rust too.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Iryna Shestak for illustrating and proof-reading this post.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>What is WASI?</title>
            <pubDate>Fri, 02 Jun 2023 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/what-is-wasi/</link>
            <guid>https://blog.yoshuawuyts.com/what-is-wasi/</guid>
            <description>&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;Now that the final touches are being put on the second version of
&lt;a href=&quot;https:&#x2F;&#x2F;wasi.dev&quot;&gt;WASI&lt;&#x2F;a&gt; (WASI Preview 2), I figured now might be a good time to
write a few words on WASI, WebAssembly, and how to think about them.
In recent months I&#x27;ve been driving the WASI Preview 2 work in the Rust compiler.
So in order to do that I&#x27;ve had to familiarize where things are currently, where
things are headed, and how build a mental model for myself. Because while Wasm
and WASI have been around for a while, WASI especially has undergone a lot of
changes. Enough so that I figured it might be helpful to write a little about.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-webassembly&quot;&gt;What is WebAssembly?&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;webassembly.org&quot;&gt;WebAssembly&lt;&#x2F;a&gt; is a &lt;em&gt;bytecode&lt;&#x2F;em&gt; format which compilers
can compile programs into. You can think of &quot;bytecode&quot; as an intermediate
format which can be converted to &lt;em&gt;native&lt;&#x2F;em&gt; formats such as &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;X86_assembly_language&quot;&gt;x86
assembly&lt;&#x2F;a&gt;, which is what
most desktop CPUs run, or &lt;a href=&quot;https:&#x2F;&#x2F;en.wikichip.org&#x2F;wiki&#x2F;arm&#x2F;armv8&quot;&gt;ARM v8
assembly&lt;&#x2F;a&gt; which is what most mobile
phones run. This is useful because it means you can &quot;compile once&quot; to
WebAssembly Bytecode, and then run that code on any number of targets - provided
they have a runtime which can interpret WebAssembly and convert it to native
code.&lt;&#x2F;p&gt;
&lt;p&gt;WebAssembly was initially designed for web browsers, to provide a way to execute
untrusted native code in a sandboxed environment. But this use case has since
expanded, because it turns out that a high-performance trusted sandbox is useful
abstraction for a lot of things - including creating sandboxed environments for
networked applications.&lt;&#x2F;p&gt;
&lt;p&gt;The best way to think about the space WebAssembly runtimes occupy is roughly at
the same level as &quot;docker containers&quot; or &quot;VMs&quot;. But rather than virtualizing an
entire operating system and managing that, WebAssembly runtimes use bytecode to
virtualize single applications. Where a single computer may concurrently execute
tens of VMs or hundreds of containers, it should be possible to run thousands of
WebAssembly programs &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#illustrative&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;illustrative&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;These are obviously not exact numbers, but more of a broad
illustration of scale. I know that for example FireCracker VMs are more
performant than regular VMs, and that people have successfully launched a million
plus docker containers in contests. But those are not typical cases, and I
believe in the &lt;em&gt;typical&lt;&#x2F;em&gt; cases what I&#x27;m saying should be broadly accurate.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;bytecode-webassembly-and-the-jvm&quot;&gt;bytecode, WebAssembly, and the JVM&lt;&#x2F;h2&gt;
&lt;p&gt;WebAssembly is sometimes compared to &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Java_bytecode&quot;&gt;Java and the
JVM&lt;&#x2F;a&gt;. This makes sense, because the
JVM is a popular platform which also interprets bytecode. The JVM not only
supports Java but any language which compiles to JVM Bytecode, including Kotlin
and Scala. However despite WebAssembly and the JVM both executing
bytecode, there are some key differences between the two:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;WebAssembly was designed to be targeted by native languages as C&#x2F;C++&#x2F;Rust in mind, while
the JVM is more oriented towards &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#graal&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; garbage-collected languages.&lt;&#x2F;li&gt;
&lt;li&gt;WebAssembly is a royalty-free &lt;a href=&quot;https:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;wasm-core-1&#x2F;&quot;&gt;W3C
standard&lt;&#x2F;a&gt;, while the JVM
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Google_LLC_v._Oracle_America,_Inc.&quot;&gt;somewhat famously&lt;&#x2F;a&gt;
isn&#x27;t. This means implementing WebAssembly support in language toolchains and
runtimes is not only possible, it&#x27;s the exact goal of the project.&lt;&#x2F;li&gt;
&lt;li&gt;WebAssembly was designed from the ground up with with strict sandboxing as a
core priority while the JVM wasn&#x27;t. In order to enable secure multi-tenancy with
the JVM it can be advisable to wrap it in another isolation layer - such as a
VM.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;graal&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;This changes a bit with the introduction of
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;oracle&#x2F;graal&quot;&gt;GraalVM&lt;&#x2F;a&gt;, but I think it still holds largely
true.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Note though that I don&#x27;t mean to harsh the JVM at all with this. WebAssembly and
the JVM were target very different use cases, have different priorities in their
design, and in turn excel at very different things.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-are-webassembly-components&quot;&gt;What are WebAssembly Components?&lt;&#x2F;h2&gt;
&lt;p&gt;WebAssembly as bytecode format is also often referred to as &quot;Core WebAssembly&quot;.
When you compile a &quot;Core WebAssembly&quot; program it is converted into something
called a &quot;WebAssembly Module&quot;. You can roughly of think of this as an object
file in traditional compilation models. But unlike classic objects, Wasm modules
can&#x27;t describe system calls or reference any external symbols - they can only
take numbers in and put numbers out, and that&#x27;s about it. If you&#x27;re trying to
make Wasm programs do anything other than sum up numbers, you need more than just Core WebAssembly.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;WebAssembly Components&quot; are a typed wrapper around Wasm Modules. Rather than
reasoning about numbers in&#x2F;numbers out, they provide a way to talk about types,
functions, methods, and namespaces. The way this is done is via an &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Interface_description_language&quot;&gt;IDL
format&lt;&#x2F;a&gt; called
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;component-model&#x2F;blob&#x2F;main&#x2F;design&#x2F;mvp&#x2F;WIT.md&quot;&gt;WIT (Wasm Interface Types)
&lt;&#x2F;a&gt;.
Here&#x27;s an example of a &quot;monotonic clock&quot; interface taken from the
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bytecodealliance&#x2F;preview2-prototyping&#x2F;blob&#x2F;main&#x2F;wit&#x2F;deps&#x2F;clocks&#x2F;monotonic-clock.wit&quot;&gt;preview2-prototyping
repo&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;default interface &lt;&#x2F;span&gt;&lt;span&gt;monotonic-clock {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;use poll&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;.{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;pollable&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A timestamp in nanoseconds.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;type instant &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;u64
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Read the current value of the clock.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The clock is monotonic, therefore calling this function repeatedly will
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; produce a sequence of non-decreasing values.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;now&lt;&#x2F;span&gt;&lt;span&gt;: func() -&amp;gt; instant
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Query the resolution of the clock.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;resolution&lt;&#x2F;span&gt;&lt;span&gt;: func() -&amp;gt; instant
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Create a `pollable` which will resolve once the specified time has been
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; reached.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;subscribe&lt;&#x2F;span&gt;&lt;span&gt;: func(
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;when&lt;&#x2F;span&gt;&lt;span&gt;: instant,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;absolute&lt;&#x2F;span&gt;&lt;span&gt;: bool
&lt;&#x2F;span&gt;&lt;span&gt;    ) -&amp;gt; pollable
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A Wasm Component is a single typed object consisting of a Core WASM Module plus
corresponding WIT definitions. Components can specify they either &lt;em&gt;export&lt;&#x2F;em&gt;
specific interfaces, or require that other interfaces are &lt;em&gt;imported&lt;&#x2F;em&gt;. For
example, I could write a binary program which prints the number of seconds
elapsed, which &lt;em&gt;exports&lt;&#x2F;em&gt; a main function with no arguments, and &lt;em&gt;imports&lt;&#x2F;em&gt; both
the &lt;code&gt;stdout&lt;&#x2F;code&gt; and &lt;code&gt;monotonic_clock&lt;&#x2F;code&gt; interfaces.&lt;&#x2F;p&gt;
&lt;p&gt;One way to think about Wasm Components is: &quot;What if we had ML-style modules in
our linker?&quot;, and that thought was taken all the way through from the system
call layer to the way libraries are linked to each other. With the added benefit
that each Wasm Component operates as its own security boundary, using a
&quot;shared-nothing&quot; approach to ensure isolation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-wasi&quot;&gt;What is WASI?&lt;&#x2F;h2&gt;
&lt;p&gt;WASI stands for the &quot;WebAssembly System Interface&quot;. Some people have recently
also started dubbing it the &quot;WebAssembly &lt;em&gt;Standard&lt;&#x2F;em&gt; Interfaces&quot;, since it
covers far more than just operating system interfaces. The way I think about
this is as sets of &lt;em&gt;standard&lt;&#x2F;em&gt; Wasm Components which can be implemented by any
vendor and targeted by any toolchain. This can include APIs such as
socket-based networking, or filesystem access. But also APIs such as HTTP-based
clients and servers, or even message queue interfaces.&lt;&#x2F;p&gt;
&lt;p&gt;Not all WASI interfaces are created equally though. For example: a serverless
environment may not want to expose direct access to the filesystem. Or the
stdlib of a programming language may not want to provide access to message queue
APIs. This differentiation in goals is why WASI has a notion of &quot;Worlds&quot;. The
different &quot;Worlds&quot; are still in the process of being defined, but the
following two are actively being worked on right now:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A world modeling a traditional operating system, providing access to sockets,
stdio, filesystem access, etc.&lt;&#x2F;li&gt;
&lt;li&gt;A world modeling a &quot;bursty&quot; environment, typically best suited for serverless
applications. This will include access to handling HTTP requests, making HTTP
requests, access to object storage, message queues, etc.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The way WASI interfaces are standardized is via the W3C&#x27;s WebAssembly working
group. People from across the industry come together to work on defining these
interfaces, which once accepted are then publish as a standard. This is
&quot;standard&quot; with a capital s. The standardization process can take time, but it
has the upside that once ratified you can know for a fact just about everyone in
the space will be adopting it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;categorizing-webassembly&quot;&gt;Categorizing WebAssembly&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we&#x27;ve talked about what Wasm and WASI &lt;em&gt;are&lt;&#x2F;em&gt;, let&#x27;s talk about what they
&lt;em&gt;aren&#x27;t&lt;&#x2F;em&gt;. Or well, perhaps more: what they aren&#x27;t &lt;em&gt;just&lt;&#x2F;em&gt;. WebAssembly falls into
multiple categories all at once, which means it also kind of escapes
categorization entirely. Depending on which angle you take, you can think of
WebAssembly as:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A programming language&lt;&#x2F;strong&gt;: The WebAssembly text format &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;WebAssembly&#x2F;Understanding_the_text_format&quot;&gt;is based on
S-Expressions&lt;&#x2F;a&gt;,
and it can be authored by hand if you want to. WIT is a similar format
targeted towards linkers, and incorporates a lot of work from the ML world.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;An operating system&lt;&#x2F;strong&gt;: Whether you&#x27;re running WASI on Windows, on Linux, or
directly on hardware - the host you&#x27;re targeting is WASI, and it should behave
the same everywhere. From a programmer&#x27;s perspective, WASI &lt;em&gt;becomes&lt;&#x2F;em&gt; the
operating system. The exact details of what&#x27;s backing the runtime shouldn&#x27;t
matter.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;A virtual machine&lt;&#x2F;strong&gt;: Wasm provides strict sandboxing guarantees, meaning that
you&#x27;re able to trust a WebAssembly runtime with the same guarantees as you
would trust a VM. A Wasm program cannot ever jump out of its current memory, and
access memory of a different program running on the same computer. But it goes
one step further:&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;An application runtime&lt;&#x2F;strong&gt;: Part of WASI are definitions for service-level APIs
such as &quot;HTTP handling&quot; and &quot;message queue access&quot;. APIs which wouldn&#x27;t be out
of place in an application runtime such as dotnet, or a cloud vendor such as Azure.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;A single-host container orchestrator&lt;&#x2F;strong&gt;: rather than dynamically linking
applications on the same host via HTTP, WASI provides an alternate model to
dynamically link programs without sharing any memory.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;A compiler&lt;&#x2F;strong&gt;: WebAssembly itself is a bytecode format which is the target of
language toolchains. But the Wasm runtimes themselves need to take that
bytecode and convert it to machine code, which means there is a &lt;a href=&quot;https:&#x2F;&#x2F;bytecodealliance.org&#x2F;articles&#x2F;cranelift-progress-2022&quot;&gt;lot of
compiler work involved&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;An ABI, memory model, and linker&lt;&#x2F;strong&gt;: Wasm Components in many ways &lt;em&gt;are&lt;&#x2F;em&gt; the
platform ABI. And because of how sandboxing has been implemented, one could
argue that Wasm has its own memory model. And the linker is basically
an ML module system in disguise. All put together, it&#x27;s basically its own
model of a system, which behaves quite differently from most traditional
platforms.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In &lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;embrace-the-kinda&#x2F;&quot;&gt;&quot;Embrace the Kinda&quot;&lt;&#x2F;a&gt;
SunfishCode talks about the categorical ambiguity of WebAssembly in more detail.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;iterating-on-wasi&quot;&gt;Iterating on WASI&lt;&#x2F;h2&gt;
&lt;p&gt;The latest version of WASI currently available is called: &quot;WASI Preview 1&quot;. For
the past four years people have been hard at work on defining &quot;WASI Preview 2&quot;,
and everything I&#x27;ve written about in this post has been about Preview 2. The
Preview 1 version of WASI was much closer to &lt;em&gt;just&lt;&#x2F;em&gt; an operating system layer.
But it quickly became clear that this would hit some pretty big limitations, and
if WASI wanted to live up to its stated goals, it would need to change.&lt;&#x2F;p&gt;
&lt;p&gt;Preview 2 is a complete rework of Preview 1, introducing WIT, WASM Components,
and all sorts of new standard interfaces. What it doesn&#x27;t yet do is provide
first-class async primitives, which is scheduled for WASI Preview 3. Threads are
also missing from Preview 2, and work on that is still ongoing.&lt;&#x2F;p&gt;
&lt;p&gt;One neat thing of the way WASI is structured is that virtualization layers can
be nested. In order to make upgrading between WASI versions easier, a shim, a
shim will be provided which allows Preview 1 code to continue working in hosts
which only implement Preview 2.&lt;&#x2F;p&gt;
&lt;p&gt;Preview releases are intentionally backwards-incompatible, and the idea is for
them to be deprecated over time. Eventually the plan is to release a &quot;WASI 1.0&quot;
specification which &lt;em&gt;will&lt;&#x2F;em&gt; provide more stability. The hope, at least, is that
with each WASI preview release, the number of changes between major versions
will shrink - so that the final 1.0 release will represent mostly a
formalization of what people have already been using for a while.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-future-of-wasi&quot;&gt;The future of WASI&lt;&#x2F;h2&gt;
&lt;p&gt;As mentioned, WASI Preview 2 doesn&#x27;t yet have a model for first-class async, or
for threading. But it also doesn&#x27;t yet provide any reasoning for multi-host
(distributed) linking of programs, nor are all of the WASI interfaces fully
specified yet. These are all things coming down the pipeline, which I&#x27;m really
excited about. Specifically for first-class async, the plan is to model that
using a structured model. Having access to that in&lt;&#x2F;p&gt;
&lt;p&gt;Beyond core WASI features, there is a lot of other interesting work ongoing.
Maybe most interesting in my opinion is the paper: &lt;a href=&quot;https:&#x2F;&#x2F;dl.acm.org&#x2F;doi&#x2F;10.1145&#x2F;3582016.3582023&quot;&gt;&lt;em&gt;&quot;Going beyond the Limits of
SFI: Flexible and Secure Hardware-Assisted In-Process Isolation with
HFI&quot;&lt;&#x2F;em&gt;&lt;&#x2F;a&gt; which was a joint project
between UCSD, Intel, and Fastly to provide a new set of instructions to make
in-process sandboxing faster and cheaper. This should greatly benefit
WebAssembly, allowing it to sandbox with even less overhead.&lt;&#x2F;p&gt;
&lt;p&gt;Work on WASI Preview 2 is currently ongoing, and should be released later this
year. On behalf of Microsoft I&#x27;m currently working on the Preview 2
implementation for rustc together with folks from Fastly and Fermyon. But work
is simultaneously happening for other language toolchains, runtimes, and
platforms as well. With WASI Preview 2 including async socket support (though
not yet multi-threading), I think this may finally be the year WebAssembly is
finally going to start living up to its expectations. And I&#x27;m incredibly excited
for that!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;The way I roughly think about WebAssembly is as a hopeful vision of what
computing can be. It represents an opportunity to take the last 40 years of
operating system research, compiler development, and industry experience and
combines that into a form that is both coherent and accessible. I hope this post
can provide some insight on what WebAssembly and WASM are, and where things are
headed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;appendix-a-terminology-cheat-sheet&quot;&gt;Appendix A: Terminology Cheat Sheet&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Wasm&lt;&#x2F;strong&gt;: short for &quot;WebAssembly&quot;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;WebAssembly&lt;&#x2F;strong&gt;, or &quot;Core WebAssembly&quot;: A bytecode format which can be translated
to native code by a &quot;WebAssembly interpreter&quot; or &quot;WebAssembly runtime&quot;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;WASI&lt;&#x2F;strong&gt;: short for &quot;WebAssembly System Interface&quot;. Sometimes also referred to as:
&quot;WebAssembly Standard Interface&quot;. It provides a set of standardized component
interfaces using the WIT IDL language.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;WIT&lt;&#x2F;strong&gt;: short for &quot;WebAssembly Interface Types&quot; is a language to define
inter-component interfaces. It is used as part of WASM Components.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;IDL&lt;&#x2F;strong&gt;: &quot;Interface Description Language&quot; is a meta-language which defines program
interfaces. WIT is an example of an IDL.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;WASM Module&lt;&#x2F;strong&gt;: best thought of as &quot;object files&quot; for WebAssembly. It&#x27;s a single
binary object containing core WASM bytecode.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;WebAssembly Component&lt;&#x2F;strong&gt;: a typed wrapper around a WASM Module. It combines a
typed WIT interface and WASM module to create a typed component.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;WebAssembly Worlds&lt;&#x2F;strong&gt;: A combination of different WASI interfaces, packaged
up into single environments. The brunt of development work in this space is
currently happening to define an &quot;operating system world&quot;, and a &quot;bursty
world&quot; (serverless).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;WASI Preview 1&lt;&#x2F;strong&gt;: The snapshot of WASI development which was released in 2019.
This wasn&#x27;t originally versioned and was previously just referred to as &quot;WASI&quot;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;WASI Preview 2&lt;&#x2F;strong&gt;: The version of WASI which is being releasing later this
year, built on top of WASM Components.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Linker&lt;&#x2F;strong&gt;: A program which glues a number of other programs together into a
single program. The parts which are glued together are usually called
&quot;libraries&quot; or &quot;objects&quot;, and the output program is usually called a &quot;binary&quot;.
With WASM Components the differences between libraries and binaries are much
less clear.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
        </item>
        <item>
            <title>Pattern Extensions</title>
            <pubDate>Fri, 26 May 2023 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/pattern-extensions/</link>
            <guid>https://blog.yoshuawuyts.com/pattern-extensions/</guid>
            <description>&lt;p&gt;Microsoft Build is happening this week, and with it come new announcements for
the C# language and dotnet runtime. I was watching the video: &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=hq6uEaMYf5U&quot;&gt;&quot;What&#x27;s new in
C#12 and beyond&quot;&lt;&#x2F;a&gt;, and the C#
team talked about pattern matching and pattern constructors. I&#x27;ve been thinking
a bit about patterns in Rust recently, and I wanted to share some of my doodles.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Disclaimer time: I&#x27;m not on the Rust language team, nor do I hold any direct
decision making power. This post is not intended to be a complete or consistent
proposal, but rather to share some short ideas which seem neat. I&#x27;m not suggesting
we should prioritize this work over any other work, nor arguing that this should
be a high priority item. The reason I&#x27;m writing this is because I like to keep up with
programming languages - and C# made some cool announcements this week.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;shapes-of-types&quot;&gt;Shapes of types&lt;&#x2F;h2&gt;
&lt;p&gt;For the purpose of this post I want to distinguish between three different
shapes of types. The shapes are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;List types, or &quot;arrays&quot; in Rust&lt;&#x2F;li&gt;
&lt;li&gt;Sum types, or &quot;enums&quot; in Rust&lt;&#x2F;li&gt;
&lt;li&gt;Product types, or &quot;structs&quot; in Rust&lt;&#x2F;li&gt;
&lt;li&gt;String types, such as &lt;code&gt;&quot;hello&quot;&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Ranges, such as &lt;code&gt;1..5&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is intentionally not a comprehensive list; neither on the side of the
shapes, nor on the side of the examples. For example: in Rust we also have
string-shaped items; and we also have vectors which are a kind of list. But this
is intentionally not a complete list - just enough of a categorization to allow
us to work through the remainder of this post.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pattern-initializers&quot;&gt;Pattern Initializers&lt;&#x2F;h2&gt;
&lt;p&gt;In Rust we have different kinds of initializer syntax available today:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;];        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Initialize an array containing twelve zeros
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; f = Foo {};         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Initialize a struct &amp;quot;Foo&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = Result::Ok(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Initialize the enum `Result` to `Ok`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; r = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;;           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Initialize a range of one to five
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; s = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Initialize a static str to &amp;quot;hello&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s take the list-initializer syntax as an example. Say we wanted to
initialize not an array, but a vec. The way we would write that today would be
by doing:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x = vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;vec![]&lt;&#x2F;code&gt; macro is built into Rust, and imported by default so this works
for &lt;code&gt;Vec&lt;&#x2F;code&gt;. But if we for example wanted to initialize a
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;collections&#x2F;struct.VecDeque.html&quot;&gt;&lt;code&gt;VecDeque&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
we&#x27;d be out of luck for the short-hand syntax, and we&#x27;d need to go through a
struct constructor instead.&lt;&#x2F;p&gt;
&lt;p&gt;In C# 12 a new feature is added which is called &quot;collection literals&quot;
(&lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;hq6uEaMYf5U?t=1123&quot;&gt;demo&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dotnet&#x2F;csharplang&#x2F;blob&#x2F;main&#x2F;proposals&#x2F;collection-literals.md&quot;&gt;spec&lt;&#x2F;a&gt;)
which allows you to opt-in types to make use of constructor literal syntax. In
the demo they take an example of &lt;code&gt;ImmutableList&lt;&#x2F;code&gt;, and allow it to be constructed
using the same syntax as a regular list. You can watch the demo or read the spec
to get a full picture of how this works in C#. But in Rust we could imagine
doing something very similar via a trait. Roughly sketching it out, you could
imagine this could work something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; v = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;];               &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; array
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; v: Vec&amp;lt;_&amp;gt; = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;];       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Vec
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; v: VecDeque&amp;lt;_&amp;gt; = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;];  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; VecDeque
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;pattern-matching&quot;&gt;Pattern Matching&lt;&#x2F;h2&gt;
&lt;p&gt;Pattern matching is another interesting feature in Rust. In C# pattern matching
was added in (if I&#x27;m not mistaken) C# 6, and has seen steady improvements over
the past number of releases. In Rust we&#x27;ve had pattern matching since the very
beginning, but what we can match on has remained fairly limited to a number of
built-ins over time.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s take a look again at the venerable list type in Rust: the array. We can
match on arrays by using the &lt;code&gt;[]&lt;&#x2F;code&gt; notation. Take for example the following,
whose first arm will match on the content of the array because it&#x27;s the same:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; x {
&lt;&#x2F;span&gt;&lt;span&gt;    [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;] =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;    _ =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For arrays that&#x27;s all well and good. But for other list types it&#x27;s more
complicated. Take for example the &lt;code&gt;Vec&lt;&#x2F;code&gt; type: we can&#x27;t directly match on it
using the same &lt;code&gt;[]&lt;&#x2F;code&gt; syntax. Instead we must obtain a &lt;em&gt;slice&lt;&#x2F;em&gt; first via the
&lt;code&gt;.as_slice&lt;&#x2F;code&gt; method or using the index syntax (&lt;code&gt;[..]&lt;&#x2F;code&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x = vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; x[..] {
&lt;&#x2F;span&gt;&lt;span&gt;    [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;] =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;    _ =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But while we have a workaround to enable matching for vec, we don&#x27;t have that
option for many other container types. For example: &lt;code&gt;VecDeque&lt;&#x2F;code&gt; doesn&#x27;t
necessarily hold items in a single continguous slice of memory, so we can&#x27;t
index into it directly using &lt;code&gt;[..]&lt;&#x2F;code&gt; like we can with vec. The easiest way to do
this is to call &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;alloc&#x2F;collections&#x2F;vec_deque&#x2F;struct.VecDeque.html#method.make_contiguous&quot;&gt;&lt;code&gt;VecDeque::make_contiguous&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
to reorder items in memory and return a single unified slice. This does however
come with a runtime cost, which means we&#x27;re now trading convenience for performance:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; x = VecDeque::new();
&lt;&#x2F;span&gt;&lt;span&gt;x.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push_front&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;x.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push_back&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; x.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;make_contiguous&lt;&#x2F;span&gt;&lt;span&gt;() { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; this will re-allocate
&lt;&#x2F;span&gt;&lt;span&gt;    [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;] =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;    _ =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It would be far nicer if we could directly affect the matchers in Rust, rather
than needing to work via slices. A lot of interesting container types don&#x27;t hold
memory in contiguous slices, so obtaining a slice can be difficult or expensive.
But it is often reasonably cheap to visit items in the container, which is all
we would need to enable pattern matching to work on richer types. Just like with
initializer patterns, it&#x27;d be nice if there was a way to enable pattern matching to be implementable via the trait system. What if this was possible instead?:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; x = VecDeque::new();
&lt;&#x2F;span&gt;&lt;span&gt;x.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push_front&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;x.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push_back&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; x { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; no re-allocation because we match directly
&lt;&#x2F;span&gt;&lt;span&gt;    [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;] =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;    _ =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;pattern-types&quot;&gt;Pattern Types&lt;&#x2F;h2&gt;
&lt;p&gt;Another interesting potential extension to Rust&#x27;s pattern system is the notion
of &quot;pattern types&quot;. In &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;state-machines-3&#x2F;&quot;&gt;my series on state
machines&lt;&#x2F;a&gt; I&#x27;ve covered some of
this. But Oli pointed out that most of that actually falls under a feature
called &quot;pattern types&quot;. This would allow us to not only reason about types as we
can today, but also about their refinements &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#note&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;note&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;I hope I&#x27;m using this word correctly here lol.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Let&#x27;s say we have a &quot;double&quot; function, which takes a number and doubles it. In
order for it to fit in the same number type, the number can&#x27;t be more than half
as big. Because if we double it, we don&#x27;t want to overflow the number type or use a bigger container. If we hand-coded this today, we&#x27;d probably want to write something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;u32_double&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;num&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; num &amp;gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MAX &lt;&#x2F;span&gt;&lt;span&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        panic!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;number cannot be doubled without overflowing&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    num + num
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;u32_double&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ✅ ok
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;u32_double&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MAX&lt;&#x2F;span&gt;&lt;span&gt;);         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ❌ panic, numbers are too big
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This has an issue that this check exists entirely at runtime. If we initialize a
number literal such as in our passing example, we hope that the compiler&#x27;s
optimizer kicks in and removes the check. But there is no guarantee that it
will. Instead using pattern types we can move this guarantee into the type
system, and we can omit the check in most cases. Using entirely made-up syntax,
you could imagine this could look something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; lol, idk what this should look like. let&amp;#39;s just pretend ok?
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; N: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MAX &lt;&#x2F;span&gt;&lt;span&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;u32_double&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;num&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt; is 0..N) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    num + num
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;u32_double&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ✅ ok
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;u32_double&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MAX&lt;&#x2F;span&gt;&lt;span&gt;);         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ❌ compile error: doesn&amp;#39;t fit in the pattern range
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Pattern types would be nice for a number of other reasons too. As previously
mentioned, I believe they would make it easier to work with
the type state pattern in Rust. But I also believe they would allow to be more
specific about borrowing, enable libary authors to define their own &lt;code&gt;NonZero&lt;&#x2F;code&gt;
types. But also provide us with what I believe may be the most ergonomic syntax
for &lt;code&gt;try&lt;&#x2F;code&gt;-functions:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; function notation
&lt;&#x2F;span&gt;&lt;span&gt;try &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt; throws Err&amp;lt;io::Error&amp;gt; {..}  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Result
&lt;&#x2F;span&gt;&lt;span&gt;try &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt; throws None {..}            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Option
&lt;&#x2F;span&gt;&lt;span&gt;try &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt; throws Break&amp;lt;()&amp;gt; {..}       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ControlFlow
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; closure notation
&lt;&#x2F;span&gt;&lt;span&gt;try || {}                     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; infer everything
&lt;&#x2F;span&gt;&lt;span&gt;try || throws None {}         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; infer success path
&lt;&#x2F;span&gt;&lt;span&gt;try || -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span&gt;{}              &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; infer error path
&lt;&#x2F;span&gt;&lt;span&gt;try || -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt; throws None {}  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; infer nothing
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Tangent time: (it&#x27;s my blog and you can&#x27;t tell me what to do).
But what I like about this in particular is that it syntactically separates the
fallibiliy aspects of the function from the base of the function.
This is especially nice because for closure notations this allows us to provide
partial ascriptions. Most of the time you can probably just write &lt;code&gt;try ||&lt;&#x2F;code&gt; and
the inference engine will help you out. But it&#x27;s nice when you can write more of
the signature when you need to. Anyway, to close this out: I think pattern types
are pretty neat and they feel like they are a bit of a non-feature. In the sense
that they (at least to me) don&#x27;t really change anything about the idea of Rust, they just
allow more code to compile which people reasonably could assume should already compile today.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-is-keyword&quot;&gt;the &quot;is&quot; keyword&lt;&#x2F;h2&gt;
&lt;p&gt;Rust recently (1.42, I know I know) stabilized the &lt;code&gt;matches!&lt;&#x2F;code&gt; macro which allows
you to use patterns for comparisons. The way this works is as follows (taken from the docs):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; foo = &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;;
&lt;&#x2F;span&gt;&lt;span&gt;assert!(matches!(foo, &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;..=&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Z&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39; | &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;..=&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;z&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; bar = Some(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert!(matches!(bar, Some(x) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; x &amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It takes a variable on the left side, and a pattern on the right side, and then
compares the two. This is often nice to have when working within expressions
such as macros. Prior to the macro, it was common (and still is common) to add
&lt;code&gt;is_&lt;&#x2F;code&gt; methods to enums, such as:
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;result&#x2F;enum.Result.html#method.is_ok&quot;&gt;&lt;code&gt;Result::is_ok&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
to allow easy comparisons within expressions.
In C# (and other languages too) there exists the &lt;a href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-US&#x2F;dotnet&#x2F;csharp&#x2F;language-reference&#x2F;operators&#x2F;is&quot;&gt;&lt;code&gt;is&lt;&#x2F;code&gt;
keyword&lt;&#x2F;a&gt;
which elevates this to a language feature. With it we could rewrite the previous
example as:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; foo = &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;;
&lt;&#x2F;span&gt;&lt;span&gt;assert!(foo is &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;..=&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Z&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39; | &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;..=&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;z&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; bar = Some(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert!(bar is Some(x) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; x &amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Whether this feature would carry its weight is a good question. Right now it&#x27;s
good practice to add &lt;code&gt;is_&lt;&#x2F;code&gt; methods for each enum member, which is a lot of typing. So much so that &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust-analyzer&#x2F;pull&#x2F;7570&quot;&gt;I added a
generator to Rust-Analyzer for
it&lt;&#x2F;a&gt; to automate the process. If every member in
every enum would benefit from a corresponding method, maybe having it as a
language feature would not be a bad idea? &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#as-conversion&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;as-conversion&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Tangent: I&#x27;m still wondering about a different timeline where the &lt;code&gt;as&lt;&#x2F;code&gt;
keyword would make use of &lt;code&gt;Into&lt;&#x2F;code&gt; instead of doing primitive casts. And &lt;code&gt;as?&lt;&#x2F;code&gt;
could be mapped to &lt;code&gt;TryInto&lt;&#x2F;code&gt;. I don&#x27;t know enough about the topic to say
anything about why that isn&#x27;t the case &#x2F; couldnt&#x27;t be made to work. But conceptually I kind of like the idea of having both &lt;code&gt;as&lt;&#x2F;code&gt; and &lt;code&gt;is&lt;&#x2F;code&gt; as a pair of keywords to operate on types.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;on-product-patterns&quot;&gt;On Product Patterns&lt;&#x2F;h2&gt;
&lt;p&gt;At the start of this post I mentioned there are a number of shapes types can be,
but so far we&#x27;ve only looked at list types. I&#x27;ve been looking at C# and while
support for matching on product types (&lt;a href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;dotnet&#x2F;csharp&#x2F;fundamentals&#x2F;functional&#x2F;pattern-matching#multiple-inputs&quot;&gt;C#
Records&lt;&#x2F;a&gt;)
seems to roughly match to what Rust is doing - I&#x27;m less sure about what the
story will be for constructing or matching on e.g. hashmap structures. It seems
the following syntax (&lt;a href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;dotnet&#x2F;csharp&#x2F;programming-guide&#x2F;classes-and-structs&#x2F;object-and-collection-initializers&quot;&gt;collection
initializers&lt;&#x2F;a&gt;)
is supported today to construct hashmaps:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c#&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-c# &quot;&gt;&lt;code class=&quot;language-c#&quot; data-lang=&quot;c#&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;var &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data &lt;&#x2F;span&gt;&lt;span&gt;= new Dictionary&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    { &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;test&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;val&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; }, 
&lt;&#x2F;span&gt;&lt;span&gt;    { &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;test2&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;val2&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; }
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This isn&#x27;t quite the same as &lt;em&gt;collection literals&lt;&#x2F;em&gt;, and I also don&#x27;t know what
that the future plans for pattern matching are in C#. Also I&#x27;m kind of coming up
empty for other languages on how e.g. matching on arbitrary product types should
look like. That&#x27;s a long way of saying: for any record types that aren&#x27;t just
structs, I&#x27;m unsure what the syntax should be. But because we&#x27;re fun-posting,
here&#x27;s three potential options that I&#x27;m somewhat certain are all not a good
idea:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Ehhhh option 1: reinterpret struct tokens as
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; values. This seems really weird and bad?
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Downside: record names are not string literals,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; and string literals are not the only possible keys.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x: HashMap&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static str&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; = {
&lt;&#x2F;span&gt;&lt;span&gt;    hello: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    world: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; x {
&lt;&#x2F;span&gt;&lt;span&gt;    { hello: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;, world: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13 &lt;&#x2F;span&gt;&lt;span&gt;} =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;    _ =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Ehhhh option 2: Literals in both the key and the value
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; position kind of like JS Object notation.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Downside: this syntax is ambiguous, because it&amp;#39;s 
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; the same as block scope syntax.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x: HashMap&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static str&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; = {
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;world&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; x {
&lt;&#x2F;span&gt;&lt;span&gt;    { &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;world&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13 &lt;&#x2F;span&gt;&lt;span&gt;} =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;    _ =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Ehhhh option 3: The only initializer syntax is [],
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; so we tuple our way through it.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Downside: this implies ordering where there is none.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x: HashMap&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static str&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; = [
&lt;&#x2F;span&gt;&lt;span&gt;    (&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    (&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;world&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; x {
&lt;&#x2F;span&gt;&lt;span&gt;    [(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;), (&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;world&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;)] =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;    _ =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Anyway tldr: where pattern initializers and matchers for list-like types seem
like a relatively straighforward design, a syntax for product types (maps,
sets) seems much less obvious to me.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;on-string-patterns&quot;&gt;On String Patterns&lt;&#x2F;h2&gt;
&lt;p&gt;In Rust 2021 we already &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;edition-guide&#x2F;rust-2021&#x2F;reserving-syntax.html&quot;&gt;reserved token
prefixes&lt;&#x2F;a&gt;
with the intent of allowing new string literals such as &lt;code&gt;f&quot;hello {world}&quot;&lt;&#x2F;code&gt; for
format strings or &lt;code&gt;s&quot;&quot;&lt;&#x2F;code&gt; for allocated strings. So we&#x27;re already somewhat on the way
to expand initializer syntax. I think it would make sense if we could work in
the inverse and as we work on that also allow the inverse to work:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Rust today
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span&gt;String::from(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; =&amp;gt; {}   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ❌ Compile error: expected `String`, found `&amp;amp;str`
&lt;&#x2F;span&gt;&lt;span&gt;    _ =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; What if something like this could work instead?
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; (string literals + string matching)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; s&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; {    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; String literal constructor
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; =&amp;gt; {}   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; String pattern matching (without casting to string slice)
&lt;&#x2F;span&gt;&lt;span&gt;    _ =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;As I mentioned at the start, this is a bit of a rambly&#x2F;braindumpy post because I
saw some cool C# things today and I wanted to write about that. I think it&#x27;s fun
to think through what it could look like if Rust&#x27;s pattern system became more
capable. To briefly recap what we&#x27;ve shown about pattern initializers + matchers:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Creating + matching on a `VecDeque` today.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; x = VecDeque::new();
&lt;&#x2F;span&gt;&lt;span&gt;x.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push_front&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;x.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push_back&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; x.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;make_contiguous&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;] =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;    _ =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Creating + matching on a `VecDeque` if we had
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; implementable list initializers + list patterns
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; x: VecDeque = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; x {
&lt;&#x2F;span&gt;&lt;span&gt;    [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;] =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;    _ =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s all. ✌️&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Linear Types One-Pager</title>
            <pubDate>Tue, 28 Mar 2023 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/linear-types-one-pager/</link>
            <guid>https://blog.yoshuawuyts.com/linear-types-one-pager/</guid>
            <description>&lt;p&gt;This post represents an overview of an MVP &quot;linear types&quot; design which we could
probably start implementing and validating &lt;em&gt;today&lt;&#x2F;em&gt; if we wanted to. What I&#x27;m
sharing here is a combination of conversations I&#x27;ve had with
&lt;a href=&quot;https:&#x2F;&#x2F;toot.cat&#x2F;@sheevink@mas.to&#x2F;110075570001413021&quot;&gt;Gankra&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;toot.cat&#x2F;@sheevink@mas.to&#x2F;110075570001413021&quot;&gt;Jonas
Sheevink&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;prior-reading&quot;&gt;Prior Reading&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;faultlore.com&#x2F;blah&#x2F;linear-rust&#x2F;&quot;&gt;The Pain Of Real Linear Types in Rust&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2023&#x2F;03&#x2F;16&#x2F;must-move-types&#x2F;&quot;&gt;Must move types&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;linearity-and-control&#x2F;&quot;&gt;Linearity and Control&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;what-are-linear-types&quot;&gt;What are linear types?&lt;&#x2F;h2&gt;
&lt;p&gt;We typically frame linear types as: &lt;em&gt;&quot;Real &lt;code&gt;#[must_use]&lt;&#x2F;code&gt; types&quot;&lt;&#x2F;em&gt;.  But it seems
like what we should be doing is framing linear types as: &lt;em&gt;&quot;Types which guarantee
their destructor will be called.&quot;&lt;&#x2F;em&gt; This is enough to provide the benefit we
feature we actually want: a guarantee that destructors will be called, so we can
rely on them for soundness purposes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-minimal-implementation&quot;&gt;A minimal implementation&lt;&#x2F;h2&gt;
&lt;p&gt;The estimate is that something like this would probably take a skilled compiler
engineer on the order of days, not weeks or months, to validate:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;We define a new &lt;code&gt;unsafe&lt;&#x2F;code&gt; (auto-)trait named &lt;code&gt;Leak&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;Leave&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;Forget&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;All bounds take an implicit &lt;code&gt;+ Leak&lt;&#x2F;code&gt; bound, like we do for &lt;code&gt;+ Sized&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Certain functions such as &lt;code&gt;mem::forget&lt;&#x2F;code&gt; will always keep taking &lt;code&gt;+ Leak&lt;&#x2F;code&gt; bounds.&lt;&#x2F;li&gt;
&lt;li&gt;Functions which want to opt-in to linearity can take &lt;code&gt;+ ?Leak&lt;&#x2F;code&gt; bounds.&lt;&#x2F;li&gt;
&lt;li&gt;Types which want to opt-in to linearity can implement &lt;code&gt;!Leak&lt;&#x2F;code&gt; or put a
&lt;code&gt;PhantomLeak&lt;&#x2F;code&gt; type in a field.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This wouldn&#x27;t require any special type of &lt;code&gt;Drop&lt;&#x2F;code&gt; either, we just guarantee it
will always be called for all &lt;code&gt;!Leak&lt;&#x2F;code&gt; types. I have a feeling this
design is actually really close to what Niko was describing in his post. The
main difference is that we consider a destructor being run as enough to satisfy
the &quot;must use&quot; semantics of linear types. So the only difference between linear
and affine types is that linear types can&#x27;t be safely passed to APIs such as
&lt;code&gt;mem::forget&lt;&#x2F;code&gt; and &lt;code&gt;Arc::new&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;interactions-with-control-flow&quot;&gt;Interactions with control flow&lt;&#x2F;h2&gt;
&lt;p&gt;The only way to prevent &lt;code&gt;Drop&lt;&#x2F;code&gt; from running is if we pass it to &lt;code&gt;mem::forget&lt;&#x2F;code&gt;,
create a cycle using &lt;code&gt;Rc&lt;&#x2F;code&gt;, &lt;code&gt;Arc&lt;&#x2F;code&gt;, or using &lt;code&gt;static&lt;&#x2F;code&gt;. The first relies on the &lt;code&gt;ManuallyDrop&lt;&#x2F;code&gt;
built-in, the second relies on the &lt;code&gt;UnsafeCell&lt;&#x2F;code&gt; built-in, and the last is a
language item. We can disallow the use of &lt;code&gt;!Leak&lt;&#x2F;code&gt; types in &lt;code&gt;static&lt;&#x2F;code&gt; lang items.
And for the functions we can make it so the bounds will always need to take &lt;code&gt;+ Leak&lt;&#x2F;code&gt;, meaning all of their derivatives will too. If a function wants to use
take &lt;code&gt;?Leak&lt;&#x2F;code&gt; as a bound and pass it to &lt;code&gt;+ Leak&lt;&#x2F;code&gt; types, the only way to do that
is via an unsafe cast. That would mean it is on the hook for upholding the
safety invariants of the &lt;code&gt;?Leak&lt;&#x2F;code&gt; type. All other interactions with e.g.
&lt;code&gt;panic!&lt;&#x2F;code&gt;, &lt;code&gt;.await&lt;&#x2F;code&gt;, or &lt;code&gt;?&lt;&#x2F;code&gt; would Just Work as expected and we don&#x27;t need to do
anything for them.&lt;&#x2F;p&gt;
&lt;p&gt;If people want to put a &lt;code&gt;!Leak&lt;&#x2F;code&gt; type in an &lt;code&gt;Arc&lt;&#x2F;code&gt;, they can create an unsafe
wrapper which temporarily removes the &lt;code&gt;!Leak&lt;&#x2F;code&gt; bound from the type, and put that
in an &lt;code&gt;Arc&lt;&#x2F;code&gt;. They&#x27;d then be manually on the hook for ensuring destructors are
run, but that&#x27;s okay.&lt;&#x2F;p&gt;
&lt;p&gt;For async types, we don&#x27;t yet have a &lt;code&gt;async Drop&lt;&#x2F;code&gt; design. But &lt;code&gt;!Leak&lt;&#x2F;code&gt; types
would guarantee that &lt;code&gt;async Drop&lt;&#x2F;code&gt; is always run. This would be enough to
guarantee the &quot;must consume&quot; semantics we want for certain types.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;drawbacks-and-challenges&quot;&gt;Drawbacks and Challenges&lt;&#x2F;h2&gt;
&lt;p&gt;This scheme would work and could be implemented in record time. In my opinion we
should do this on nightly, just to prove that it can be done. Once done we can
tackle the ergonomics issues this creates:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;We would want to go through the entire stdlib and mark almost every
generic param as &lt;code&gt;+ ?Leak&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Because trait bounds are instantly stable, we would have no trial period to
test out a linear bound, before committing to it.&lt;&#x2F;li&gt;
&lt;li&gt;Just like how &lt;code&gt;?Sized&lt;&#x2F;code&gt; describes &quot;maybe-dyn&quot;, &lt;code&gt;?Leak&lt;&#x2F;code&gt; describes
&quot;maybe-must-move&quot;. Because we&#x27;re talking in terms of negation, it is really
hard to reason about. Our dyn system is notorious for being some of the hardest
to understand part of Rust.&lt;&#x2F;li&gt;
&lt;li&gt;Assuming all but a few bounds in the stdlib will eventually take &lt;code&gt;?Leak&lt;&#x2F;code&gt;, will
we ever want to switch to make that the default across an edition to reduce line
noise? If we think we might, we should think about what that would look like.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Leak&lt;&#x2F;code&gt; introduces new safety rules for Rust which must be upheld when
declaring &lt;code&gt;?Leak&lt;&#x2F;code&gt; or &lt;code&gt;!Leak&lt;&#x2F;code&gt; bounds. Those will need to be spelled out in detail
before &lt;code&gt;Leak&lt;&#x2F;code&gt; can be stabilized.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I believe that just like with &lt;code&gt;dyn&lt;&#x2F;code&gt;, &quot;must not move&quot;, send, etc we should look
at an alternate formulation of these bounds by treating them as built-in
effects. That would allow us to address the issues of versioning, visual noise,
etc. in a more consistent and ergonomic way. But that&#x27;s not a requirement to
start testing this out, so if we believe we want this feature, starting with the
design in this document seems to me like the right way to go.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;updates&quot;&gt;Updates&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;update 2023-05-03:&lt;&#x2F;strong&gt; &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Skepfyr&quot;&gt;Jack Rickard&lt;&#x2F;a&gt; pointed out that &lt;code&gt;!Leak&lt;&#x2F;code&gt; types and &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;keyword.static.html&quot;&gt;statics&lt;&#x2F;a&gt;
have bad interactions. Types which are placed in statics don&#x27;t have their
destructors run when the program exits. Which means that if we allowed &lt;code&gt;!Leak&lt;&#x2F;code&gt;
types to be placed inside statics, it would prevent destructors from running
entirely. This would break the linearity guarantees. so statics have to be a
no-no for linear types. This puts linearity right next to const in that statics
are fundamentally disallowed.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;2023-05-04:&lt;&#x2F;strong&gt; From talking more to Jack Rickard, we created another example of
&quot;safe forget&quot; using &lt;code&gt;thread::spawn&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;safe_forget&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;val&lt;&#x2F;span&gt;&lt;span&gt;: T) {
&lt;&#x2F;span&gt;&lt;span&gt;    thread::spawn(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;|| {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; val = val;                   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; move `val` into the thread
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{ std::thread::park(); }    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; park the thread indefinitely
&lt;&#x2F;span&gt;&lt;span&gt;    });                                  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; drop the thread thandle
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The thread handle becomes unreachable, detaching the thread, and holding the
value until the main thread exits - at which point destructors won&#x27;t run
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#alternate-thread&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. This is contrast to &lt;code&gt;thread::scope&lt;&#x2F;code&gt;, which is
tree-structured and wouldn&#x27;t allow doing this. To me this seems to indicate
three things:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;In order to guarantee destructors are run, it&#x27;s key to prevent cycles. This
holds for both data (&lt;code&gt;Rc&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;Arc&lt;&#x2F;code&gt;) and computation (&lt;code&gt;thread::spawn&lt;&#x2F;code&gt;). I&#x27;ve got
a hunch that structured concurrency is very closely connected to what we&#x27;re
trying to do here.&lt;&#x2F;li&gt;
&lt;li&gt;If we are to introduce linearity into Rust, we need to follow the path we&#x27;ve
taken with &lt;code&gt;const&lt;&#x2F;code&gt;. One API at the time, validating the linearity guarantees
at each stage. This emphasizes the need to have a formalization of the safety
rules.&lt;&#x2F;li&gt;
&lt;li&gt;Even in this model we need to have a way to express &lt;code&gt;?Leak Fn&lt;&#x2F;code&gt; to enable
closing over &lt;code&gt;!Leak&lt;&#x2F;code&gt; types. This adds further credibility to the idea that
we will want some form of surface syntax for &lt;code&gt;!leak fn&lt;&#x2F;code&gt;, to be able to
declare free functions which can be passed into linear closure position. This
is in addition to the existing &lt;code&gt;!leak async fn&lt;&#x2F;code&gt; use case.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;alternate-thread&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;It makes me wonder about an alternate timeline where
&lt;code&gt;JoinHandle&lt;&#x2F;code&gt; would be &lt;code&gt;!Leak&lt;&#x2F;code&gt; and implement &quot;join on drop&quot; semantics. Had that
been the case, then &lt;code&gt;thread::spawn&lt;&#x2F;code&gt; would probably have been okay to close over
&lt;code&gt;!Leak&lt;&#x2F;code&gt; types.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</description>
        </item>
        <item>
            <title>Linearity and Control</title>
            <pubDate>Thu, 23 Mar 2023 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/linearity-and-control/</link>
            <guid>https://blog.yoshuawuyts.com/linearity-and-control/</guid>
            <description>&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Update 2023-03-28&lt;&#x2F;strong&gt;: I&#x27;ve published &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;linear-types-one-pager&#x2F;&quot;&gt;a follow-up to this
post&lt;&#x2F;a&gt; which presents an
alternate design, reframing linearity as: &quot;Drop is guaranteed to run&quot;. To get a
full overview of the design space, read this post to get a sense of the problem
domain, and the follow-up post for a concrete solution.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;A week ago Niko published &lt;a href=&quot;http:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2023&#x2F;03&#x2F;16&#x2F;must-move-types&#x2F;&quot;&gt;a post on linear types&lt;&#x2F;a&gt;, introducing
the idea of &quot;must move&quot; types, which he suggested could be implemented through
some form of &lt;code&gt;?Drop&lt;&#x2F;code&gt; bound. It&#x27;s far from the first time linear types have come
up. Five years ago Gankra &lt;a href=&quot;https:&#x2F;&#x2F;faultlore.com&#x2F;blah&#x2F;linear-rust&#x2F;&quot;&gt;also published a post&lt;&#x2F;a&gt; on linear types,
explaining what they are and why they&#x27;re hard to get right.&lt;&#x2F;p&gt;
&lt;p&gt;In this post I want to build on these two posts; expanding on what linear types
are, why they&#x27;re useful, how they would interact with Rust, and share a novel
effect-based design — which unlike many previous attempts would preserve our
ability to implement and use destructors.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Before we dive in I want to extend an enormous thanks to Eric Holk, for first
positing the idea that linearity obligations might be transferable up the call
stack or ownership chain. That has been the key insight on which the majority of
the design in this post builds.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;⚠️ &lt;em&gt;Disclaimer: The syntax in this post is entirely made up, and meant as
illustrative only. While it may be tempting to discuss syntax, this post is
primarily focused on semantics instead. I am not a member of the language team.
I do not speak for the language team. This post does not encode any decisions
made by the language team. The point of this post is to exchange ideas, in the
open, with peers - because in my opinion that is the best way to go about
designing things.️&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-are-linear-types&quot;&gt;What are linear types?&lt;&#x2F;h2&gt;
&lt;p&gt;If you&#x27;ve been writing Rust for a little while, you&#x27;ll be familiar with
&lt;code&gt;#[must_use]&lt;&#x2F;code&gt;. Decorating a function with this attribute makes it so the types
returned from the functions &lt;em&gt;must be used&lt;&#x2F;em&gt; or else it produces a warning.
But &lt;code&gt;#[must_use]&lt;&#x2F;code&gt; is limited. &quot;using&quot; in this context means &quot;doing literally
anything with the function output&quot;. As long as we do that, &lt;code&gt;#[must_use]&lt;&#x2F;code&gt; is
happy. This includes, or example, passing it to &lt;code&gt;mem::forget&lt;&#x2F;code&gt; or &lt;code&gt;Box::leak&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;must_use_fn&lt;&#x2F;span&gt;&lt;span&gt;();              &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ⚠️ &amp;quot;unused return value of `must_use_fn` that must be used&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;must_use_fn&lt;&#x2F;span&gt;&lt;span&gt;();      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ✅ no warnings or errors
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;_ = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;must_use_fn&lt;&#x2F;span&gt;&lt;span&gt;();      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ✅ no warnings or errors
&lt;&#x2F;span&gt;&lt;span&gt;mem::forget(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;must_use_fn&lt;&#x2F;span&gt;&lt;span&gt;()); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ✅ no warnings or errors
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However there are often cases where we would like a more rigorous version of
&lt;code&gt;#[must_use]&lt;&#x2F;code&gt;. Say we have a &lt;code&gt;Transaction&lt;&#x2F;code&gt; type. It has a method &lt;code&gt;new&lt;&#x2F;code&gt; to create
a transaction, a method &lt;code&gt;commit&lt;&#x2F;code&gt; to finalize the transaction successfully, and a
method &lt;code&gt;abort&lt;&#x2F;code&gt; to finalize the transaction unsuccessfully.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A type representing a transaction.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Transaction { .. }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Transaction {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Create a new instance of `Transaction`.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ .. }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Finalize `Transaction` successfully.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;commit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) { .. }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Finalize `Transaction` unsuccessfully.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;abort&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) { .. }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What we&#x27;d like to express here is that if you call &lt;code&gt;new&lt;&#x2F;code&gt;, you &lt;em&gt;must&lt;&#x2F;em&gt; call either
&lt;code&gt;commit&lt;&#x2F;code&gt;, or &lt;code&gt;abort&lt;&#x2F;code&gt;. But Rust&#x27;s type system doesn&#x27;t let us express this yet.
Even &lt;code&gt;Drop&lt;&#x2F;code&gt; wouldn&#x27;t help us here, since the type system doesn&#x27;t guarantee it&#x27;ll
ever be called. What we&#x27;d like is for the following to be possible:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;_ = Transaction::new(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ❌ &amp;quot;unused return value of `Transaction::new` that must be used&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The reason for this is that Rust type system supports &lt;em&gt;affine&lt;&#x2F;em&gt; types, but does
not support &lt;em&gt;linear&lt;&#x2F;em&gt; types. This is a common misconception, but the difference
between them is actually pretty important:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;affine types&lt;&#x2F;strong&gt; are types which must can be used &lt;em&gt;at most once&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;linear types&lt;&#x2F;strong&gt; are types which must be used &lt;em&gt;exactly once&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This means that Rust can guarantee you won&#x27;t use the same type twice (e.g. we systemically prevent
&lt;a href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;cpp&#x2F;sanitizers&#x2F;error-double-free?view=msvc-170&quot;&gt;double
free&lt;&#x2F;a&gt;s from happening);
but for example we can&#x27;t guarantee that values &lt;em&gt;will&lt;&#x2F;em&gt; have methods called on
them (e.g. we can&#x27;t prevent memory from leaking). Being able to express
linearity in Rust would likely also enable us to solve some of the other
challenges we&#x27;ve been facing:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;async scopes&lt;&#x2F;strong&gt;: &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;thread&#x2F;fn.scope.html&quot;&gt;&lt;code&gt;thread::scope&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; allows us to share variables between
threads without using locks. An &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; version of this would
require linear types to function &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#tmandry-post&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;true session types&lt;&#x2F;strong&gt;: This is best explained as: &quot;What if we could model the
semantics of entire network protocols using the type system.&quot; We can get close
today, but to fully encode session types we require access to linear types
[^session-type-limits]  &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#philip-wadler&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;more efficient completion-based IO&lt;&#x2F;strong&gt;: APIs such as &lt;code&gt;io_uring&lt;&#x2F;code&gt; have very specific
rules about how objects should be passed between the kernel and the program.
Linear types should make it possible to model these interactions with
significantly less runtime overhead &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#io-uring-note&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;more efficient async C++ FFI&lt;&#x2F;strong&gt;: The &lt;code&gt;Future&lt;&#x2F;code&gt;-equivalent in C++ &lt;em&gt;must&lt;&#x2F;em&gt; be
polled to completion because if you don&#x27;t you trigger UB. This is unlike
Rust&#x27;s &lt;code&gt;Future&lt;&#x2F;code&gt; type which can be dropped to be cancelled. Linear types would
allow us to model this behavior directly in Rust&#x27;s type system.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;tmandry-post&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Tmandry wrote &lt;a href=&quot;https:&#x2F;&#x2F;tmandry.gitlab.io&#x2F;blog&#x2F;posts&#x2F;2023-03-01-scoped-tasks&#x2F;&quot;&gt;a good post about the challenges of async
scopes&lt;&#x2F;a&gt;. While he
doesn&#x27;t directly spell out how linear types would help solve some of these
issues &lt;a href=&quot;http:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2023&#x2F;03&#x2F;16&#x2F;must-move-types&#x2F;#uses-for-must-move&quot;&gt;Niko
does&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;session-types-limits&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;The paper &lt;a href=&quot;https:&#x2F;&#x2F;dl.acm.org&#x2F;doi&#x2F;abs&#x2F;10.1145&#x2F;2808098.2808100&quot;&gt;&quot;Session types for
Rust&quot;&lt;&#x2F;a&gt; writes in their
conclusion: &lt;em&gt;&quot;We have demonstrated that session types can be implemented
directly in a language supporting affine types, and argued for its safety. Like
linear types, affine types prevent aliasing, but, unlike linear types, fail to
promise progress.&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;philip-wadler&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;There&#x27;s a cool
&lt;a href=&quot;https:&#x2F;&#x2F;homepages.inf.ed.ac.uk&#x2F;wadler&#x2F;papers&#x2F;propositions-as-types&#x2F;propositions-as-types.pdf&quot;&gt;paper&lt;&#x2F;a&gt;
and &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=IOiZatlZtGU&quot;&gt;talk&lt;&#x2F;a&gt; titled &quot;Propositions as
Types&quot; by Phil Wadler who makes the point that every good idea is
&lt;em&gt;discovered&lt;&#x2F;em&gt;, not invented. In the talk at the 37:00 mark he mentions that
linear logic and session types seem to correspond to each other, and may in fact
provide us with a solution to way to formally encode concurrency and
distribution. Whether that&#x27;s actually true, I don&#x27;t know for sure - I&#x27;m not a
professor in theoretical computer science like Phil is, nor have I ever used
linear types or session types to say anything from experience. But it certainly
seems plausible, which I think should be enough to get anyone excited who&#x27;s
trying to build reliable networked services.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;io-uring-note&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Tbh I&#x27;m not an expert on &lt;code&gt;io_uring&lt;&#x2F;code&gt;, so I might not be 100% on
point here. I&#x27;m basing my understanding of this mostly on the fact that the
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;spacejam&#x2F;rio&quot;&gt;&lt;code&gt;rio&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; library would be considered sound
if the destructors could be guaranteed to run. The point of linear types is to
provide such a guarantee, which means linearity could be a way to model
completion-based IO safely and ergonomically, directly from Rust.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;To provide a quick example of something which is inexpressible in Rust today: we
can&#x27;t create an &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; version of
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;thread&#x2F;fn.scope.html&quot;&gt;&lt;code&gt;thread::scope&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; in Rust
today. But using linear types, we could require that the future returned by
&lt;code&gt;async_scope&lt;&#x2F;code&gt; is awaited, and that in the event of a cancellation, the
destructors of &lt;code&gt;async_scope&lt;&#x2F;code&gt; are guaranteed to run for as long as tasks are
live, ensuring we maintain Rust&#x27;s property of preventing all data races in safe
Rust &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#gankra-leakpocalypse&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;gankra-leakpocalypse&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;This is a very similar problem Gankra described in here
2015 post on why &lt;a href=&quot;https:&#x2F;&#x2F;faultlore.com&#x2F;blah&#x2F;everyone-poops&#x2F;&quot;&gt;why &lt;code&gt;mem::forget&lt;&#x2F;code&gt; should be
safe&lt;&#x2F;a&gt;. It caused us to remove
&lt;code&gt;thread::scope&lt;&#x2F;code&gt; from the stdlib until its reintroduction in 2022. Unfortunately
the tricks we applied to make this work in stable Rust today won&#x27;t work for
async Rust; which means we have to solve this issue &lt;em&gt;for real this time&lt;&#x2F;em&gt; if we
want it to be possible.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; a = vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; x = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;async_scope&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;| {
&lt;&#x2F;span&gt;&lt;span&gt;    s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(|| {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello from the first scoped task&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; We can borrow `a` here.
&lt;&#x2F;span&gt;&lt;span&gt;        dbg!(&amp;amp;a);
&lt;&#x2F;span&gt;&lt;span&gt;    });
&lt;&#x2F;span&gt;&lt;span&gt;    s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(|| {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello from the second scoped task&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; We can even mutably borrow `x` here,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; because no other tasks are using it.
&lt;&#x2F;span&gt;&lt;span&gt;        x += a[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] + a[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;    });
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello from the main task&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}).await;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; After the scope, we can modify and access our variables again:
&lt;&#x2F;span&gt;&lt;span&gt;a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(x, a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;create-and-consume&quot;&gt;Create and consume&lt;&#x2F;h2&gt;
&lt;p&gt;Okay, time to get into the details of the design. At the heart of a linear
type&#x27;s lifecycle are two phases: create (or &quot;construct&quot;) and consume (or
&quot;destruct&quot;). A linear type promises at the type system level that once it&#x27;s
created, it will &lt;em&gt;always&lt;&#x2F;em&gt; be consumed. The way we&#x27;re modeling this in our design
is using type instantiation to create and &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;reference&#x2F;patterns.html#destructuring&quot;&gt;pattern destructuring&lt;&#x2F;a&gt; to consume&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;firstyear&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;firstyear&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;This example was inspired by Firstyear&#x27;s post on &lt;a href=&quot;https:&#x2F;&#x2F;fy.blackhats.net.au&#x2F;blog&#x2F;html&#x2F;2021&#x2F;11&#x2F;14&#x2F;transactional_operations_in_rust.html&quot;&gt;Transactional
Operations in
Rust&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; txn = Transaction { .. };  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 1. Create a new instance of `Transaction`.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; Transaction { .. } = txn;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 2. Consume an instance of `Transaction`.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;No matter what happens in the code, every linear type which is created
will always have a matching consume. This means that as long as your program
has an opportunity to run to completion it is &lt;em&gt;guaranteed&lt;&#x2F;em&gt; to be consumed. Yay
for type systems!&lt;&#x2F;p&gt;
&lt;p&gt;In this post we&#x27;ll be modeling this via the introduction of a new effect kind
(or &quot;modifier keyword&quot; if you prefer): &lt;code&gt;linear&lt;&#x2F;code&gt;. Don&#x27;t worry too much about the
name, I&#x27;m mostly using it for clarity throughout this post. This effect can be
applied to either types or functions; but we&#x27;ll start with types.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;linear-types&quot;&gt;Linear types&lt;&#x2F;h3&gt;
&lt;p&gt;When a type is marked as &lt;code&gt;linear&lt;&#x2F;code&gt; it means that once a type has been
created, in order for it to type-check it must also be consumed. This will
be automatically done by the type checker for you, who will gently tell you if
you messed up anywhere. But by using &lt;code&gt;unsafe&lt;&#x2F;code&gt; you can also do this by hand if
you need to. More on that later though.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;linear &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Transaction { .. }
&lt;&#x2F;span&gt;&lt;span&gt;linear &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;Foo { .. }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is not the end of linear types though: a key feature of types is that they
can be composed into new types. When a type takes a linear type as an argument,
the &quot;linearity&quot; obligation transfers to the enclosing type. This means that a
linear type can only be held by another linear type:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;linear &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;TransactionWrapper {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;txn&lt;&#x2F;span&gt;&lt;span&gt;: Transaction, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; linear type
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;linear-functions&quot;&gt;Linear functions&lt;&#x2F;h3&gt;
&lt;p&gt;The second place where the &lt;code&gt;linear&lt;&#x2F;code&gt; notation can be used is on functions and
methods. The way this would look is like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Transaction {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ .. }
&lt;&#x2F;span&gt;&lt;span&gt;    linear &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;commit&lt;&#x2F;span&gt;&lt;span&gt;(linear &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) { .. }
&lt;&#x2F;span&gt;&lt;span&gt;    linear &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;abort&lt;&#x2F;span&gt;&lt;span&gt;(linear &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) { .. }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Functions which don&#x27;t take any linear types as arguments don&#x27;t have to be marked as
&lt;code&gt;linear fn&lt;&#x2F;code&gt; which is why &lt;code&gt;fn new&lt;&#x2F;code&gt; is not marked linear here &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#linear-fn&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. But if a function wants
to take a linear type as an argument, it needs to be marked as a &lt;code&gt;linear fn&lt;&#x2F;code&gt;.
Every linear function needs to promise it will do one of three things for every
instance of a linear type which is passed to it:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;linear-fn&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;Folks in review asked me: &quot;why doesn&#x27;t &lt;code&gt;fn new&lt;&#x2F;code&gt; need to be
linear?&quot; The real reason is because it doesn&#x27;t follow the rules I&#x27;m setting out
in this post. But it could very well be that it would me a lot more clear if
only linear functions could yield linear types, in which case this should be
&lt;code&gt;linear fn new&lt;&#x2F;code&gt;. As I&#x27;ve said at the start of this post: syntax is something we
can dig into once we know the semantics we want to expose. And answering this
question really is just a matter of syntax.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;ol&gt;
&lt;li&gt;It will destruct the instance.&lt;&#x2F;li&gt;
&lt;li&gt;It will yield the instance to the caller along with control over execution.&lt;&#x2F;li&gt;
&lt;li&gt;It will call another linear function and pass the instance along as an argument.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This might sound easy enough, but in practice this has implications for what
&lt;em&gt;can&#x27;t&lt;&#x2F;em&gt; be done, such as:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;It will not &lt;code&gt;mem::forget&lt;&#x2F;code&gt; any instances of linear types.&lt;&#x2F;li&gt;
&lt;li&gt;It will not create any cycles around instances of linear types using &lt;code&gt;Arc&#x2F;Rc&lt;&#x2F;code&gt; or similar.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;If we can imagine a parallel version of the stdlib where all types and functions
which can be linear &lt;em&gt;are&lt;&#x2F;em&gt; in fact linear: &lt;code&gt;mem::forget&lt;&#x2F;code&gt;, &lt;code&gt;Arc::new&lt;&#x2F;code&gt;, and
&lt;code&gt;Rc::new&lt;&#x2F;code&gt; would not exist. And our safety rules would disallow creating new
&lt;code&gt;linear fn&lt;&#x2F;code&gt;s which don&#x27;t uphold those rules. Being able to mark which functions
uphold the rules of linearity is exactly the purpose of the &lt;code&gt;linear fn&lt;&#x2F;code&gt;
notation.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;linear-contexts&quot;&gt;Linear contexts&lt;&#x2F;h3&gt;
&lt;p&gt;The &quot;must consume&quot; obligation of a linear function only applies to arguments
which themselves are also linear. It should be possible to pass non-linear
arguments to linear functions without any problem, allowing you to mix and match
linear and non-linear types within a linear function.&lt;&#x2F;p&gt;
&lt;p&gt;Similarly: it should be possible to create linear types and call linear
functions from non-linear functions. This means you should be able to create
and consume linear types from your existing functions largely without problems.
The exceptions here are probably &lt;code&gt;async&lt;&#x2F;code&gt; contexts, and things like closure
captures: both of those create types which wrap existing types. So when they
capture a linear type, they themselves must become linear too. We&#x27;ll get into
more detail on how that works later on in this post.&lt;&#x2F;p&gt;
&lt;p&gt;This means that it should be possible to for example have an &lt;code&gt;fn main&lt;&#x2F;code&gt; which is
not marked &lt;code&gt;linear&lt;&#x2F;code&gt; which creates and consumes linear types in its function
body:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 1. Non-linear function context.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; txn = Transaction { .. };  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 2. Create a new instance of `Transaction`.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; Transaction { .. } = txn;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 3. Consume an instance of `Transaction`.
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If for whatever reason we do find a good reason why linear types should only be
accessible from linear contexts, we could do that. Just like with &lt;code&gt;const {}&lt;&#x2F;code&gt; we
could create a &lt;code&gt;linear {}&lt;&#x2F;code&gt; context which can be used to close out the linearity
effect. But I don&#x27;t think that is necessary, and I suspect linear types would be
easier to use if we didn&#x27;t require this. This is almost a question of syntax
though, so it&#x27;s probably not worth going too deep into this right now.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;linear-methods&quot;&gt;Linear methods&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;ve sort of hinted at this, but not said it out loud: for linear types to
be really useful it&#x27;s not enough if we have types which cannot be dropped. What
we really want is pairs of methods which need to be called.&lt;&#x2F;p&gt;
&lt;p&gt;In Rust we don&#x27;t have &quot;class constructors&quot; built into the language as a feature.
Instead what we have is struct initialization, and methods such as
&lt;code&gt;MyStruct::new&lt;&#x2F;code&gt; or &lt;code&gt;MyStruct::open&lt;&#x2F;code&gt; to construct the type. The reason why these
work is because they&#x27;re the only places in the code which have access to the
struct&#x27;s private fields. So to create the struct, they&#x27;re the only way to do it.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Transaction {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ 
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{ field1, field2 }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Similarly with linear types what we don&#x27;t want is for people to require access to
private fields to destruct their types. Instead we can just create methods which
can do the destruction for us. This means that the only way to close out the
&lt;code&gt;linear&lt;&#x2F;code&gt; effect&#x27;s requirements is to call a destructor method on the type:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Transaction {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt; linear &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;commit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let Self &lt;&#x2F;span&gt;&lt;span&gt;{ field1, field2 } = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt; linear &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;abort&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) { 
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let Self &lt;&#x2F;span&gt;&lt;span&gt;{ field1, field2 } = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As we discussed earlier: the only valid thing to do with an instance of a linear
type is to either consume it, return it, or pass it to another linear function.
&quot;linear destructors&quot; do the latter: they&#x27;re linear functions which consume a
linear type. So from a compiler&#x27;s perspective this is exactly right.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;linear-drop&quot;&gt;Linear drop&lt;&#x2F;h3&gt;
&lt;p&gt;A key feature feature in Rust is the ability to define &lt;code&gt;Drop&lt;&#x2F;code&gt; destructors
(&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Resource_acquisition_is_initialization&quot;&gt;RAII&lt;&#x2F;a&gt;).
For example when you create a file using &lt;code&gt;File::open&lt;&#x2F;code&gt;, its &lt;code&gt;Drop&lt;&#x2F;code&gt; destructor
will make sure that the file is closed when it goes out of scope. Syntactically
this makes code a lot nicer to read, because rather than needing to remember
which function to call inside a function body, the type implementing &lt;code&gt;Drop&lt;&#x2F;code&gt; will
just auto-cleanup all resources for you.&lt;&#x2F;p&gt;
&lt;p&gt;To ensure &quot;linear Rust&quot; is as ergonomic as non-linear Rust, code should largely
feel the same as well. This includes having access to &lt;code&gt;Drop&lt;&#x2F;code&gt;. The way we could
do this is by introducing a linear version of &lt;code&gt;Drop&lt;&#x2F;code&gt;, which rather than take
&lt;code&gt;&amp;amp;mut self&lt;&#x2F;code&gt; takes &lt;code&gt;self&lt;&#x2F;code&gt;. And when called requires the existing rules of
linearity are upheld. The way this destructor would work is that it would &lt;em&gt;only&lt;&#x2F;em&gt;
run when a type goes out of scope. It would &lt;em&gt;not&lt;&#x2F;em&gt; run if a type is manually
destructed.&lt;&#x2F;p&gt;
&lt;p&gt;People may be wondering at this point what the difference between linear types
and affine types then is, if both get access to destructors. With affine types
we can&#x27;t guarantee that destructors will run, so we can&#x27;t build on it for the
purpose of soundness. With linear types we can make that guarantee, so we
destructors can be relied on for the purpose of soundness.&lt;&#x2F;p&gt;
&lt;p&gt;In our &lt;code&gt;Transaction&lt;&#x2F;code&gt; example, we can imagine that we might to abort the
transaction unsuccessfully if it goes out of scope. But we would want to
successfully commit it by hand if we&#x27;ve succeeded. We could do that by adding
the following &lt;code&gt;linear Drop&lt;&#x2F;code&gt; implementation:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;linear Drop for Transaction {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;(linear &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;abort&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This would make it so if the transaction goes out of scope or if we call &lt;code&gt;abort&lt;&#x2F;code&gt;
it aborts. But only if we call &lt;code&gt;commit&lt;&#x2F;code&gt; manually does it complete successfully:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;do_thing&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Result&amp;lt;()&amp;gt; {      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 1. No linear arguments, so no `linear fn` needed.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; txn = Transaction::new();  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 2. Create a new transaction.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;some_action&lt;&#x2F;span&gt;&lt;span&gt;()?;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 3. On error, drop `txn` and call the destructor.
&lt;&#x2F;span&gt;&lt;span&gt;    txn.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;commit&lt;&#x2F;span&gt;&lt;span&gt;();                  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 4. On success, call `txn.commit`.
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(())                         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 5. Return from the function; no linear types are live.
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Admittedly I&#x27;m not entirely sure whether &lt;code&gt;linear Drop&lt;&#x2F;code&gt; in fact requires taking
&lt;code&gt;linear Self&lt;&#x2F;code&gt; to be destructed, or whether it would suffice for Drop to keep
taking &lt;code&gt;&amp;amp;mut self&lt;&#x2F;code&gt; as an argument, assuming that if the destructor is called, it
will be destructed anyway. The most important difference between &lt;code&gt;linear Drop&lt;&#x2F;code&gt;
and regular Drop is that linear Drop will not run if the type is manually
destructed. And that unlike regular Drop, linear types &lt;em&gt;guarantee&lt;&#x2F;em&gt; they will be
destructed. The exact details of the interfaces are secondary to the semantics
we&#x27;re trying to encode.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;control&quot;&gt;Control&lt;&#x2F;h2&gt;
&lt;p&gt;In this section I&#x27;ll be covering the interactions of linear types with
control-flow primitives such as &lt;code&gt;panic&lt;&#x2F;code&gt; and &lt;code&gt;async&lt;&#x2F;code&gt;. Creating a coherent model
for their interactions is a requirement to make linear types practical.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;control-points&quot;&gt;Control Points&lt;&#x2F;h3&gt;
&lt;p&gt;You may have heard of the term &quot;control flow&quot; to refer to things like branches,
loops, and function calls. It describes the &quot;flow&quot; of control over execution.
Perhaps you&#x27;ve also heard of &quot;control flow operators&quot; to refer to things like
&lt;code&gt;if&lt;&#x2F;code&gt;, &lt;code&gt;while&lt;&#x2F;code&gt;, and &lt;code&gt;for..in&lt;&#x2F;code&gt; which are the specific keywords we use to encode
control flow operations. In the compiler all of these things are tracked in a
data structure called the &quot;control-flow graph&quot; (CFG).&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve found there is a term here missing, which is something I&#x27;ve started
calling &quot;control points&quot;: places in the code where the callee hands control over
execution back to its caller. The caller then may or may not hand control back
to the callee &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#structured-lang&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Not all control-flow operations are equal
though. We can divide them into two categories:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;structured-lang&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;&#x2F;sup&gt;
&lt;p&gt;This does not include points at which control over execution
is handed off to another function by calling it. In structured programming
languages such as Rust we can treat those as black boxes, so from the function&#x27;s
perspective we only have to observe what happens when they hand control back to
us again.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Breaking operations&lt;&#x2F;strong&gt;: hand control back to the caller, and that&#x27;s it. Examples:
&lt;code&gt;return&lt;&#x2F;code&gt;, &lt;code&gt;break&lt;&#x2F;code&gt;, &lt;code&gt;continue&lt;&#x2F;code&gt;, &lt;code&gt;?&lt;&#x2F;code&gt;, &lt;code&gt;panic!&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Suspending operations&lt;&#x2F;strong&gt;: hand control back to the caller, but the caller can
choose to hand control &lt;em&gt;back&lt;&#x2F;em&gt; to the callee again later. Examples:
&lt;code&gt;.await&lt;&#x2F;code&gt;, &lt;code&gt;yield&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I&#x27;m using &quot;caller&quot; and &quot;callee&quot; somewhat loosely here, since Rust is
expression-oriented and with things like &lt;code&gt;try {}&lt;&#x2F;code&gt; blocks and inline &lt;code&gt;loop {}&lt;&#x2F;code&gt;,
control flow doesn&#x27;t necessarily need to be handed to a different function. It
can be enough to be handed to an enclosing scope. Let&#x27;s take a look at a
reasonably representative Rust function which does some async IO and then some
parsing:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;do_something&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: PathBuf) -&amp;gt; io::Result&amp;lt;Table&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; file = fs::open(&amp;amp;path).await?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; table = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;parse_table&lt;&#x2F;span&gt;&lt;span&gt;(file)?;
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(table)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And here it is again, with all control points fully annotated:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;do_something&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: PathBuf) -&amp;gt; io::Result&amp;lt;Table&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;                                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 1. futures start suspended, and may not resume again
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; file = fs::open(&amp;amp;path).await?;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 2. `.await` suspends, and may not resume again
&lt;&#x2F;span&gt;&lt;span&gt;                                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 3. `?` propagates errors to the caller
&lt;&#x2F;span&gt;&lt;span&gt;                                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 4. `fs::open` may panic and unwind
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; table = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;parse_table&lt;&#x2F;span&gt;&lt;span&gt;(file)?;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 5. `?` propagates errors to the caller
&lt;&#x2F;span&gt;&lt;span&gt;                                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 6. `parse_table` may panic and unwind
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(table)                           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 7. return a value to the caller
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While many of the control points in this function are visible, many others are
not. In order for linear types to function, they need to account for &lt;em&gt;all&lt;&#x2F;em&gt; control
points regardless of whether they&#x27;re visible or not. This is why it&#x27;s so
important to be able to implement &lt;code&gt;linear Drop&lt;&#x2F;code&gt; destructors. Because without
them it wouldn&#x27;t be possible to carry linear types over control points.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;liveness&quot;&gt;Liveness&lt;&#x2F;h3&gt;
&lt;p&gt;Now that we&#x27;ve covered what control points are, we can discuss how they interact
with linear types. In its most basic form: when a linear type is held live
&lt;em&gt;across&lt;&#x2F;em&gt; a control point, the compiler cannot prove that it will be consumed.
Assuming we take our earliest version of &lt;code&gt;Transaction&lt;&#x2F;code&gt; which didn&#x27;t implement
&lt;code&gt;linear Drop&lt;&#x2F;code&gt;.  If you hold a an instance of it across an &lt;code&gt;.await&lt;&#x2F;code&gt; the compiler
should throw an error. The &lt;code&gt;?&lt;&#x2F;code&gt; may cause the function to return, meaning there
is no guarantee &lt;code&gt;txn.commit&lt;&#x2F;code&gt; will ever be invoked:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;do_something&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; txn = Transaction::new();  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 1. Create an instance of `Transaction` (assuming no `linear Drop`).
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;some_action&lt;&#x2F;span&gt;&lt;span&gt;()?;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 2. ❌ `?` may cause the function to return with an error.
&lt;&#x2F;span&gt;&lt;span&gt;    txn.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;commit&lt;&#x2F;span&gt;&lt;span&gt;();                  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 3. ❌ we cannot guarantee `txn.commit` will be called.
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the reason why in order for linear types to be practical, they &lt;em&gt;must&lt;&#x2F;em&gt;
implement a form of &quot;consuming Drop&quot;. Without it we couldn&#x27;t hold any linear
types across control points. And &lt;strong&gt;because every function in Rust is currently
allowed to panic, it means having linear types without destructors would be
entirely impractical&lt;&#x2F;strong&gt;. That&#x27;s why its likely virtually every linear type will
want to implement some form of &lt;code&gt;linear Drop&lt;&#x2F;code&gt;, and there are open questions on
how deeply we could integrate this into the language:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;do_something&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; txn = Transaction::new();  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 1. Create an instance of `Transaction` (assuming `linear Drop`).
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;some_action&lt;&#x2F;span&gt;&lt;span&gt;()?;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 2. ✅ `?` may cause the function to return with an error, invoking `txn.drop`.
&lt;&#x2F;span&gt;&lt;span&gt;    txn.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;commit&lt;&#x2F;span&gt;&lt;span&gt;();                  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 3. ✅ Or `?` does not return, and `txn.commit` is called.
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The key interaction between linear types and control points is one of
&lt;em&gt;liveness&lt;&#x2F;em&gt;. When interacting with a control point, linear types must guarantee
they will remain &lt;em&gt;live&lt;&#x2F;em&gt;. This means the linear type must either being returned
from a scope via the control point, or must be able to be destructed before the
control point finishes handing control back over (e.g. &lt;code&gt;linear Drop&lt;&#x2F;code&gt;). I hope
the terminology of &quot;liveness&quot; and &quot;control points&quot; can provide us with the
missing vocabulary to talk about how linear types interact with things such as
panics and errors.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;abort-points&quot;&gt;Abort points&lt;&#x2F;h3&gt;
&lt;p&gt;It&#x27;s important to distinguish between &quot;control points&quot; and what I&#x27;m calling
here: &quot;abort points&quot;. Where control points represent points in the control-flow
graph where control over execution is handed off to another place within the
program. &quot;Abort points&quot; represent points within the program at which point the
program stops executing entirely.&lt;&#x2F;p&gt;
&lt;p&gt;In practice, every line of code represents an abort point. There is no guarantee
a computer will execute the next instruction on a CPU. The best it can do is
guarantee that &lt;em&gt;if&lt;&#x2F;em&gt; a next instruction will be run, which one it will be. Power
plugs can be pulled, CPUs can shut down processes, kernels can crash. These are
things which live outside the type system, and we cannot model within the type
system. The type system assumes that the hardware it runs on is well-behaved. If
it isn&#x27;t, the model doesn&#x27;t hold.&lt;&#x2F;p&gt;
&lt;p&gt;When we write &lt;code&gt;panic=abort&lt;&#x2F;code&gt; in our &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt; it changes the meaning of
&lt;code&gt;panic!&lt;&#x2F;code&gt; from &quot;unwind&quot; to &quot;just immediately stop&quot;. Similarly: we can use
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;process&#x2F;fn.exit.html&quot;&gt;&lt;code&gt;std::process::exit&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to
stop a program then and there. Because we exit the confines of the program, the
type system cannot meaningfully say anything about it, so linear types can&#x27;t
model it.&lt;&#x2F;p&gt;
&lt;p&gt;Similarly: we can&#x27;t treat &lt;em&gt;slow&lt;&#x2F;em&gt; operations as control points either. If a
program runs &lt;code&gt;thread::sleep(10_years)&lt;&#x2F;code&gt;, as far as the type system is concerned
that doesn&#x27;t represent a control point anymore than &lt;code&gt;thread::sleep(10_nanos)&lt;&#x2F;code&gt;
would. The only time we can really capture that a linear type is violated is in
the case of &lt;em&gt;unreachable&lt;&#x2F;em&gt; code. Take for example the following example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;do_something&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; txn = Transaction::new();  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 1. Create an instance of `Transaction`.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{}                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 2. Loop infinitely
&lt;&#x2F;span&gt;&lt;span&gt;    txn.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;commit&lt;&#x2F;span&gt;&lt;span&gt;();                  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 3. Complete the transaction.
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;… which should probably produce an error like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;error: linear type destructor is unreachable
&lt;&#x2F;span&gt;&lt;span&gt; --&amp;gt; src&#x2F;lib.rs:4:1
&lt;&#x2F;span&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;span&gt;3 | loop {}
&lt;&#x2F;span&gt;&lt;span&gt;  | ------- any code following this expression is unreachable
&lt;&#x2F;span&gt;&lt;span&gt;4 | txn.commit();
&lt;&#x2F;span&gt;&lt;span&gt;  | ^^^^^^^^^^^^^ unreachable destructor
&lt;&#x2F;span&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;async-and-linearity&quot;&gt;Async and Linearity&lt;&#x2F;h2&gt;
&lt;p&gt;Async Rust provides us with the ability to write non-blocking code in a
imperative fashion, and through its design unlocks two key capabilities:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The ability to execute any number of async operations &lt;em&gt;concurrently&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;The ability to &lt;em&gt;cancel&lt;&#x2F;em&gt; any operation before it completes by dropping its
corresponding future.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&quot;async&quot;, much like &quot;linearity&quot; can best be thought of as an &lt;em&gt;effect&lt;&#x2F;em&gt;. And when
we talk about combining async an linearity, what we&#x27;re really discussing is
&lt;em&gt;effect composition&lt;&#x2F;em&gt;. Effects are built into the language, and hold a deep
semantic relationship to the underlying program. This means that when they
interact we get to choose how they should behave together. In the case of
composing linear and async, there are two behaviors we want to be able to
encode:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;must-await futures&lt;&#x2F;strong&gt;: these are futures which must be awaited, but once
awaited may still be cancelled. Because cancellation is a very useful
property for most kinds of futures.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;must-consume futures&lt;&#x2F;strong&gt;: these are futures which not only must be awaited,
even if attempted to be cancelled, they must continue doing their work.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;In order for a future to be &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;reference&#x2F;expressions&#x2F;await-expr.html#approximate-desugaring&quot;&gt;&lt;code&gt;.await&lt;&#x2F;code&gt;ed&lt;&#x2F;a&gt;, it must first be
&lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;2023&#x2F;03&#x2F;09&#x2F;Rust-1.68.0.html#local-pin-construction&quot;&gt;&quot;stack-pinned&quot;&lt;&#x2F;a&gt;, resulting in a &lt;code&gt;Pin&amp;lt;&amp;amp;mut T&amp;gt;&lt;&#x2F;code&gt; type. In the
general case this means we&#x27;ve permanently lost access to the inner &lt;code&gt;T&lt;&#x2F;code&gt; type:
once a type has been pinned, it must remain pinned until it&#x27;s dropped. This
means that once we start polling a future, we can no longer destruct it.
That&#x27;s why for async Rust we need to expand the destructor rules of linearity
slightly. In order to &quot;consume&quot; a linear future, it should be enough to place it
inside a &lt;code&gt;.await&lt;&#x2F;code&gt; expression. Awaiting a future should be considered equivalent
to consuming a future, even if we cancel it later on. This provides us with &quot;must-use&quot;
futures:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;_ = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;meow&lt;&#x2F;span&gt;&lt;span&gt;();  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ❌ &amp;quot;`meow` returns a `Future` which must be `.await`ed&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In order to encode &quot;must-consume&quot; futures we will need access to an
async version of linear drop. As &lt;a href=&quot;https:&#x2F;&#x2F;sabrinajewson.org&#x2F;blog&#x2F;async-drop#uncancellable-futures&quot;&gt;Sabrina Jewson&lt;&#x2F;a&gt; pointed out before: if we
require a future to continue doing work when cancelled, it can continue doing
that work in its drop handler. If the drop handler itself is un-cancellable,
then we are able to construct un-cancellable futures.&lt;&#x2F;p&gt;
&lt;p&gt;Unlike the &lt;code&gt;linear Drop&lt;&#x2F;code&gt; we&#x27;ve shown before, &lt;code&gt;async linear Drop&lt;&#x2F;code&gt; cannot take
&lt;code&gt;self&lt;&#x2F;code&gt; by-value because of the pinning rules. It instead it can only really take
&lt;code&gt;&amp;amp;mut self&lt;&#x2F;code&gt;. So again, the fact that it&#x27;s being destructed will need to be
guaranteed by the fact that it&#x27;s &lt;code&gt;.await&lt;&#x2F;code&gt;ed. Encoding the linearity of &lt;code&gt;async linear Drop&lt;&#x2F;code&gt; itself is a different matter. And I suspect we&#x27;ll need to dedicate
a separate post to exactly spell out how that should work. My guess is that this
will require a connection that is as deep to the language as non-async &lt;code&gt;Drop&lt;&#x2F;code&gt;.
And that at the root of the program it will bottom out in something like it
being a linearity violation if you don&#x27;t handle the future returned by &lt;code&gt;Drop&lt;&#x2F;code&gt; to
completion. I&#x27;m not exactly sure yet how this should be done, but it seems like
it should be doable.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cycles-and-safety&quot;&gt;Cycles and Safety&lt;&#x2F;h2&gt;
&lt;p&gt;Unsafe Rust provides access to raw pointers. These are pointers, which unlike
references, may alias if you&#x27;re not careful. But just because they &lt;em&gt;could&lt;&#x2F;em&gt; alias
doesn&#x27;t mean they&#x27;re allowed to alias. And it&#x27;s in fact undefined behavior if you
fail to uphold Rust&#x27;s safety rules in unsafe Rust. &lt;code&gt;unsafe&lt;&#x2F;code&gt; only removes the
guard rails, it doesn&#x27;t change the rules.&lt;&#x2F;p&gt;
&lt;p&gt;The same would apply to &lt;code&gt;linear fn&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;linear T&lt;&#x2F;code&gt; and &lt;code&gt;unsafe&lt;&#x2F;code&gt;. It should be
possible to cast a &lt;code&gt;linear T&lt;&#x2F;code&gt; to a regular &lt;code&gt;T&lt;&#x2F;code&gt;, if you make sure to keep
treating &lt;code&gt;T&lt;&#x2F;code&gt; as if it was a &lt;code&gt;linear T&lt;&#x2F;code&gt;. This would allow you to create linear
functions which internally could hold cycles, but which externally would not be
observable. Assuming we had a &quot;make this type non-linear&quot; (&lt;code&gt;UnsafeNonLinear&lt;&#x2F;code&gt;)
equivalent to
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;cell&#x2F;struct.UnsafeCell.html&quot;&gt;&lt;code&gt;UnsafeCell&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. We
could imagine we could take an instance of &lt;code&gt;Transaction&lt;&#x2F;code&gt; and place it inside an
&lt;code&gt;Arc&lt;&#x2F;code&gt; somewhat like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; txn = Transaction::new();                     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; create a new linear transaction
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; txn = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ UnsafeNonLinear::new(txn) };   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; cast it to remove its linearity
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; txn = Arc::new(txn);                          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; place it inside an `Arc`, *may* lead to cycles
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; txn = Arc::into_inner().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; extract it from the `Arc`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; txn = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ txn.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_inner&lt;&#x2F;span&gt;&lt;span&gt;() };            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; convert it back to a linear type
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I don&#x27;t really know whether it makes most sense to create an unsafe wrapper
type, or whether we could use &lt;code&gt;as&lt;&#x2F;code&gt;-casts to peel the linearity effect. I would
expect casting a &lt;code&gt;T&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;linear T&lt;&#x2F;code&gt; would probably be safe, but I don&#x27;t know for
sure. Because this would be a new language construct we would be able to define
all of these rules. They seem like they should be fairly straightforward, so
fingers crossed it actually ends up being that way.&lt;&#x2F;p&gt;
&lt;p&gt;Finally there&#x27;s an open question we have is whether it could in fact be possible
to create linear versions of &lt;code&gt;Arc&lt;&#x2F;code&gt; and &lt;code&gt;Rc&lt;&#x2F;code&gt; (and &lt;code&gt;Mutex&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;RefCell&lt;&#x2F;code&gt;). If every
cloned instance had to prove it was consumed, would it be possible to guarantee
that no cycles may occur?  Even if that&#x27;s not possible for the existing APIs,
perhaps a different formulation could provide those guarantees. Something like a
&lt;code&gt;scope&lt;&#x2F;code&gt; API might be able to provide such guarantees. If this were possible it
would make linear APIs significantly more convenient to use, so I suspect it
would be worth examining this further.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;closure-captures&quot;&gt;Closure captures&lt;&#x2F;h2&gt;
&lt;p&gt;An interesting challenge &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;Gankra_&#x2F;status&#x2F;1636532417950253057&quot;&gt;Gankra shared on Twitter&lt;&#x2F;a&gt; is how
closure captures interact with linearity. In order for &quot;linear Rust&quot; to be as
ergonomic as non-linear Rust, the two should feel largely similar when used.
This means closures and closure captures should be accessible from linear Rust
too.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s examine an example more closely. Here is the &lt;code&gt;Option::map&lt;&#x2F;code&gt; function as
implemented in the standard library today. It takes an &lt;code&gt;Option&lt;&#x2F;code&gt;, and a closure, and
if &lt;code&gt;Some&lt;&#x2F;code&gt; applies the closure to it. If we take the &lt;code&gt;None&lt;&#x2F;code&gt; branch, at first
glance it seems like nothing will happen. But on closer inspection we may
realize that we drop the closure, and so we also drop all variables captured by
the closure:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; Option&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;U&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;: impl FnOnce(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; U) -&amp;gt; Option&amp;lt;U&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            Some(t) =&amp;gt; Some(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;(t)),
&lt;&#x2F;span&gt;&lt;span&gt;            None =&amp;gt; None,
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In Niko&#x27;s blog post, this example was adapted to use &lt;code&gt;T: ?Drop&lt;&#x2F;code&gt;. This is valid
because in the &lt;code&gt;Some&lt;&#x2F;code&gt; case the &lt;code&gt;T&lt;&#x2F;code&gt; parameter is passed to the closure, which can
consume the linear type. While in the &lt;code&gt;None&lt;&#x2F;code&gt; case there is no &lt;code&gt;T&lt;&#x2F;code&gt;, so there is
no type to consume. But as we&#x27;ve mentioned this does not account for the
variables captured by the closure, which in this formulation would likely just
be disallowed from performing any captures. Instead, using the &lt;code&gt;linear&lt;&#x2F;code&gt; effect
we can model this the way we would expect because we have access to linear
destructors, and because a linear type can only be captured by another linear
type:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;linear T&amp;gt; Option&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt; linear &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;U&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;: impl linear FnOnce(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; U) -&amp;gt; Option&amp;lt;U&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            Some(t) =&amp;gt; Some(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;(t)),
&lt;&#x2F;span&gt;&lt;span&gt;            None =&amp;gt; None,
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Because &lt;code&gt;T&lt;&#x2F;code&gt; is linear, the closure &lt;code&gt;FnOnce&lt;&#x2F;code&gt; which takes &lt;code&gt;T&lt;&#x2F;code&gt; as an argument must
also be linear, and in turn the &lt;code&gt;map&lt;&#x2F;code&gt; method must be linear as well. This
does assume that linear closures can be dropped to run the destructors of the
variables they&#x27;ve captured. Which seems reasonable, since the &lt;code&gt;Fn&lt;&#x2F;code&gt;-family of
traits are marked &lt;code&gt;#[fundamental]&lt;&#x2F;code&gt; and are part of the language - so we can
define how they should function in the presence of &lt;code&gt;linear&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;linear-stdlib&quot;&gt;Linear stdlib&lt;&#x2F;h2&gt;
&lt;p&gt;Our &lt;code&gt;linear fn map&lt;&#x2F;code&gt; example doesn&#x27;t quite capture the same semantics as Niko&#x27;s
proposal yet. This syntax &lt;em&gt;requires&lt;&#x2F;em&gt; types to be linear, whereas in Niko&#x27;s
version types &lt;em&gt;may&lt;&#x2F;em&gt; be linear - or they may not be. In order to capture this
&quot;maybe-ness&quot; of effect keywords we need a way to express it: which is what the
Keyword Generics Initiative &lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;inside-rust&#x2F;2023&#x2F;02&#x2F;23&#x2F;keyword-generics-progress-report-feb-2023.html&quot;&gt;has been working
on&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To make our effect-based design of &lt;code&gt;Option::map&lt;&#x2F;code&gt; fully compatible with the
semantics Niko laid out, we&#x27;d have to make one more change. Rather than using
&lt;code&gt;T: ?Drop&lt;&#x2F;code&gt; which communicates the presence of an effect through the absence of an
auto-trait, we can instead use &lt;code&gt;?linear T&lt;&#x2F;code&gt; to more directly communicate the
potential presence of an effect:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;linear T&amp;gt; Option&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span&gt;?linear &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;U&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;: impl ?linear FnOnce(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; U) -&amp;gt; Option&amp;lt;U&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            Some(t) =&amp;gt; Some(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;(t)),
&lt;&#x2F;span&gt;&lt;span&gt;            None =&amp;gt; None,
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;From the feedback we&#x27;ve received I know many people are not particularly
thrilled about this syntax - which is perfectly understandable. But exact syntax
aside, it&#x27;s important to observe that if we do this right, then this syntax
should be mostly temporary. Aside from a few exceptions in the stdlib (&lt;code&gt;Arc&lt;&#x2F;code&gt;,
&lt;code&gt;Rc&lt;&#x2F;code&gt;, &lt;code&gt;mem::forget&lt;&#x2F;code&gt;), most library code can probably be marked as &lt;code&gt;linear&lt;&#x2F;code&gt;.
Which begs the question: if most code can be linear, could it make sense to
eventually assume linearity, unless people opt-out? If that were the case, then
the signature of &lt;code&gt;Option::map&lt;&#x2F;code&gt; would remain identical to what it is today in the
stdlib already. But the signature of &lt;code&gt;mem::forget&lt;&#x2F;code&gt; could then become:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;forget&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;linear&amp;gt;(t: T) { .. }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It seems far more desireable to gradually &lt;code&gt;linear&lt;&#x2F;code&gt;-ify the stdlib rather than
defining a parallel &lt;code&gt;linear&lt;&#x2F;code&gt; stdlib checked into &lt;code&gt;crates.io&lt;&#x2F;code&gt; (as we&#x27;ve &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;latest&#x2F;async_std&#x2F;&quot;&gt;done once
already&lt;&#x2F;a&gt; for &lt;code&gt;async&lt;&#x2F;code&gt;). And far more
empathic than trying to argue that users of Rust are in fact wrong for wanting to
make use of APIs such as &lt;code&gt;Option::map&lt;&#x2F;code&gt; in linear contexts. Regardless of which
set of effects you&#x27;re using in Rust to program with, familiar patterns and
techniques should be accessible to all.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;movability&quot;&gt;Movability&lt;&#x2F;h2&gt;
&lt;p&gt;In his post Niko describes &quot;linear types&quot; as &quot;must-move types&quot;. This begs the
question: if there are types which &lt;em&gt;must&lt;&#x2F;em&gt; move, are other kinds of moves
possible as well? And there are. By default types in Rust can be described as
&quot;may-move types&quot;, because they can be moved but they don&#x27;t have to. And then
we also have access to &quot;must-not-move types&quot; which are represented by combining
the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;pin&#x2F;struct.Pin.html&quot;&gt;&lt;code&gt;Pin&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; type with the
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;marker&#x2F;trait.Unpin.html&quot;&gt;&lt;code&gt;!Unpin&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; trait. Though
in practice most people prefer to encode the immovability of types
using the more declarative &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;pin-project&#x2F;latest&#x2F;pin_project&#x2F;&quot;&gt;&lt;code&gt;pin-project&lt;&#x2F;code&gt;
crate&lt;&#x2F;a&gt; instead.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;must move&lt;&#x2F;strong&gt;: linear types&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;may move&lt;&#x2F;strong&gt;: the default mode of Rust types&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;must not move&lt;&#x2F;strong&gt;: pinned types&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Thinking of &quot;must-move types&quot; (linear) as the opposite of &quot;must-not-move types&quot;
(pinned) is a useful model to carry forward, as they encode opposing guarantees
about the movability of types. Reconciling these opposing guarantees is what
makes combining async + linear types difficult, since once futures start being
polled can generally no longer be moved. If this post continues into a series,
this would be a topic I&#x27;d like to revisit in more detail later on.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;further-reading&quot;&gt;Further Reading&lt;&#x2F;h2&gt;
&lt;p&gt;Gankra wrote an excellent post in 2015 on &lt;a href=&quot;https:&#x2F;&#x2F;faultlore.com&#x2F;blah&#x2F;everyone-poops&#x2F;&quot;&gt;why &lt;code&gt;mem::forget&lt;&#x2F;code&gt; should be
safe&lt;&#x2F;a&gt;, explaining why we
can&#x27;t assume destructors will always run in Rust. She wrote a follow-up post in
2017 about &lt;a href=&quot;https:&#x2F;&#x2F;faultlore.com&#x2F;blah&#x2F;linear-rust&#x2F;&quot;&gt;what makes linear types hard to
model&lt;&#x2F;a&gt;, concluding on an optimistic
note with: &quot;Ok having actually written this all out, it’s better than I
thought.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Substructural_type_system#Different_substructural_type_systems&quot;&gt;Wikipedia page on linear
types&lt;&#x2F;a&gt;
provides a useful overview of the difference between among other &quot;linear&quot; and
&quot;affine&quot; types. Including type systems with both more and less guarantees than
both. Phil Wadler&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;citeseerx.ist.psu.edu&#x2F;document?repid=rep1&amp;amp;type=pdf&amp;amp;doi=24c850390fba27fc6f3241cb34ce7bc6f3765627&quot;&gt;&quot;linear types can change the
world!&quot;&lt;&#x2F;a&gt;,
provides a great type-theoretical introduction to what linear types are, and why
they are useful. Similarly on type-theory side, Phil Wadler also published
&quot;Propositions as Types&quot;
(&lt;a href=&quot;https:&#x2F;&#x2F;homepages.inf.ed.ac.uk&#x2F;wadler&#x2F;papers&#x2F;propositions-as-types&#x2F;propositions-as-types.pdf&quot;&gt;paper&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=IOiZatlZtGU&quot;&gt;talk&lt;&#x2F;a&gt;), making an excellent case
that properties such as lambda calculus and linear types are not invented - they
are discovered. Meaning they may in fact be a fundamental part of logic and
computing.&lt;&#x2F;p&gt;
&lt;p&gt;More recently Tyler Mandry wrote a blog post on &lt;a href=&quot;https:&#x2F;&#x2F;tmandry.gitlab.io&#x2F;blog&#x2F;posts&#x2F;2023-03-01-scoped-tasks&#x2F;&quot;&gt;the challenges of defining
scoped tasks in
Rust&lt;&#x2F;a&gt;. And Niko
Matsakis wrote a post on &lt;a href=&quot;https:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2023&#x2F;03&#x2F;16&#x2F;must-move-types&#x2F;&quot;&gt;&quot;must move&quot;
types&lt;&#x2F;a&gt;,
as a potential way to overcome the challenges scoped tasks present. Miguel Young
de la Sota gave a talk about &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=UrDhMWISR3w&quot;&gt;move constructors in
Rust&lt;&#x2F;a&gt;, explaining how like in C++,
Rust could implement self-referential types which can be moved. Yosh Wuyts (hello)
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;safe-pin-projections-through-view-types&#x2F;&quot;&gt;wrote a
post&lt;&#x2F;a&gt; on
the challenges we face in order to make common interactions with pinned values
safe. Sabrina Jewson wrote a post describing the challenges of &lt;a href=&quot;https:&#x2F;&#x2F;sabrinajewson.org&#x2F;blog&#x2F;async-drop#uncancellable-futures&quot;&gt;async
destructors&lt;&#x2F;a&gt;,
going into great detail about various considerations in the design space.  And
Yosh Wuyts (hello, again) wrote a post describing how &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-cancellation-1&#x2F;&quot;&gt;async
cancellation&lt;&#x2F;a&gt; works, and why
it&#x27;s an essential capability of async Rust.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Linearity in Rust is largely inexpressible today. This leads us to work around
this restriction in various ways, which come at the cost of correctness,
performance, and ergonomics. In this post we&#x27;ve shown how linearity in Rust
could be modeled as an effect, bypassing any of these restrictions. We&#x27;ve shown
how it could be used to create ergonomics which are largely similar to existing
Rust, and how we could gradually introduce linearity into the stdlib and
ecosystem.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ve shown how for the sake of ergonomics it&#x27;s not only important to be able to
create and consume bare types, but also to be able to define constructors and
destructors which must be called as pairs. Another contribution this post has
made is formulated a model for linear &lt;code&gt;Drop&lt;&#x2F;code&gt;; which is required to preserve
Rust&#x27;s existing ergonomics in a linear context.&lt;&#x2F;p&gt;
&lt;p&gt;Finally we&#x27;ve taken a closer look at how linearity interacts with cycles, with
&lt;code&gt;unsafe&lt;&#x2F;code&gt;, and with &lt;code&gt;async&lt;&#x2F;code&gt;. For &lt;code&gt;async&lt;&#x2F;code&gt; specifically, we&#x27;ve taken a look at how
&lt;code&gt;linear async fn&lt;&#x2F;code&gt; would work, why it should not disallow cancellation by default,
and how we could use it to still encode &quot;must-not cancel&quot; semantics.&lt;&#x2F;p&gt;
&lt;p&gt;To close this post out: I don&#x27;t expect this post to function as a definitive design.
In fact, it was written with the opposite intent. I hope this post will help us
better understand the challenges linear types face in Rust, and serve as a
useful tool in getting us closer to a design which we would be happy to adopt.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;I&#x27;d like to thank Sy Brand, Iryna Shestak, and Eric Holk for reviewing this
post prior to publishing.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Using HTML as a compile target</title>
            <pubDate>Fri, 03 Feb 2023 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/compiled-html/</link>
            <guid>https://blog.yoshuawuyts.com/compiled-html/</guid>
            <description>&lt;p&gt;If you&#x27;ve been around an industry for long enough you end up with Opinions™
about things. Here&#x27;s one of mine: I think one of the biggest missing aspects of
web programming is the lack of support for treating HTML as a compile-target.&lt;&#x2F;p&gt;
&lt;p&gt;Most folks reading this blog may not be aware of this, but I started my
career working with web technologies, which I kept at for the better part of a decade.
I co-authored one of the (at least to my knowledge) first &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#first&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;stackcss&#x2F;sheetify&quot;&gt;CSS-in-JS engines&lt;&#x2F;a&gt;,
I&#x27;ve written &lt;a href=&quot;https:&#x2F;&#x2F;www.choo.io&#x2F;&quot;&gt;frontend frameworks&lt;&#x2F;a&gt;, designed &lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;choojs&#x2F;bankai-the-friendly-web-compiler-35f1916679cc&quot;&gt;web
compilers&lt;&#x2F;a&gt;,
and authored &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;http-rs&quot;&gt;entire HTTP stacks&lt;&#x2F;a&gt;. Even if
web tech isn&#x27;t really my current area of focus, it&#x27;s something I&#x27;ve worked on a
fair bit, and still care about a lot.  So here&#x27;s a post about an opinion I have,
in a field I don&#x27;t do much in currently, but still think would like to share.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;first&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;To my knowledge at the time at least. I&#x27;ll totally buy that e.g. PHP
or Google&#x27;s web compiler may have supported similar stuff - but we didn&#x27;t know
about it at the time. When we designed sheetify in ~2015 ish &lt;code&gt;css-modules&lt;&#x2F;code&gt; was
all the rage, and we figured we could do something similar without needing to
overload the meaning of &lt;code&gt;require&lt;&#x2F;code&gt;. And we didn&#x27;t know of anything that worked
similar at the time. Later,
&lt;a href=&quot;https:&#x2F;&#x2F;styled-components.com&#x2F;&quot;&gt;&lt;code&gt;styled-components&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; became a thing, citing our
work on sheetify as an inspiration. But that&#x27;s all ancient history at this
point.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;a-taste-of-html&quot;&gt;A taste of HTML&lt;&#x2F;h2&gt;
&lt;p&gt;There are well over 100 unique HTML elements in the spec. Let&#x27;s zoom in on just
one of those: the &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;HTML&#x2F;Element&#x2F;li&quot;&gt;&lt;code&gt;&amp;lt;li&amp;gt;&lt;&#x2F;code&gt; element&lt;&#x2F;a&gt;.
It inherits from a class hierarchy which is &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;HTMLLIElement&quot;&gt;4 levels
deep&lt;&#x2F;a&gt;. It
exposes two unique attribute values, of which 1 has been deprecated and
shouldn&#x27;t be used. And it can&#x27;t just be placed anywhere in the DOM: it has
exactly 4 valid parent elements, of which 1 also has been obsoleted. Here are
some examples of it in action:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;html&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-html &quot;&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;aside&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;li&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;first&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;li&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;li&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;second&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;li&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;aside&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;menu&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;li&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;first&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;li&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;li&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;second&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;li&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;menu&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Quiz time: which of these is valid? Which of these isn&#x27;t? None, both, either
one? When you write the code, you don&#x27;t know. It&#x27;s only when you try and render
the code in the browser that you&#x27;ll receive feedback.&lt;&#x2F;p&gt;
&lt;p&gt;Okay fine, the answer to the last question was that &lt;code&gt;&amp;lt;aside&amp;gt;&amp;lt;li&amp;gt;&lt;&#x2F;code&gt; is invalid,
but &lt;code&gt;&amp;lt;menu&amp;gt;&amp;lt;li&amp;gt;&lt;&#x2F;code&gt; is valid. Quiz number two (no peeking at the reference): what
is rendered here?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;html&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-html &quot;&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ol&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;li &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&amp;gt;second&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;li&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;li &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&amp;gt;first&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;li&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ol&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;menu&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;li &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&amp;gt;second&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;li&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;li &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&amp;gt;first&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;li&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;menu&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Okay, answer time: first one is valid, second one is not. But both will render,
without error. It&#x27;s just that in the first case &lt;code&gt;value&lt;&#x2F;code&gt; is respected (&quot;first,
second&quot;) while in the second case it renders &quot;second, first&quot;. Did you know that?
I sure didn&#x27;t.&lt;&#x2F;p&gt;
&lt;p&gt;As you&#x27;re probably aware I&#x27;m not actually trying to teach you the rules of
&lt;code&gt;&amp;lt;li&amp;gt;&lt;&#x2F;code&gt;, but just trying to show that this teeny tiny basic element has a host of
interactions that will affect what you build. And we&#x27;re only scratching the
surface of this element. It also interacts with styling, event handlers, ARIA roles,
and elements contained within. The fact that &lt;code&gt;value&lt;&#x2F;code&gt; attributes on &lt;code&gt;&amp;lt;li&amp;gt;&lt;&#x2F;code&gt; are
valid when nested within &lt;code&gt;&amp;lt;ol&amp;gt;&lt;&#x2F;code&gt;, but not within &lt;code&gt;&amp;lt;menu&amp;gt;&lt;&#x2F;code&gt; is just one interaction
of thousands out there. Everyone gets things wrong all the time with this. And
we need to do better. All these rules are specced, implemented, and (mostly)
consistent. We need a way to automate this knowledge.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;type-safe-html&quot;&gt;Type-Safe HTML&lt;&#x2F;h2&gt;
&lt;p&gt;I think we need to start by acknowledging that HTML is complex. Not in a
deregatory way, HTML is also really useful, but as a statement of fact. There
are more rules and interactions than anyone reasonable person can manage. Which
means we shouldn&#x27;t expect people to be the ones managing it.&lt;&#x2F;p&gt;
&lt;p&gt;Instead, I believe that HTML would benefit from &lt;em&gt;type safety&lt;&#x2F;em&gt;. Right now the
way HTML is validated is by shipping it to a browser, and then checking the
console tab for errors. Or sometimes people run linters on it such as
&lt;a href=&quot;https:&#x2F;&#x2F;developer.chrome.com&#x2F;docs&#x2F;lighthouse&#x2F;overview&#x2F;&quot;&gt;lighthouse&lt;&#x2F;a&gt; or &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pa11y&#x2F;pa11y&quot;&gt;pa11y&lt;&#x2F;a&gt;. Sometimes these things even happen in CI.&lt;&#x2F;p&gt;
&lt;p&gt;A shortcoming of this approach is that in order to validate whether you&#x27;ve done
things right, you first have to load your web page into a browser engine, and
only then you can validate whatever was rendered. But that&#x27;s where it stops: it
only validates what was rendered at that point. If your page has different
components which can be in different states, or also has different pages, you
need to ensure every one of those is validated. And that&#x27;s often more work than
it&#x27;s worth, so people don&#x27;t bother.&lt;&#x2F;p&gt;
&lt;p&gt;Instead the way I&#x27;m thinking about it is: what if we moved the validation to a
compilation pass. That way we can prevent errors from occurring altogether. A
compiler is able to reason about all states, and validate they&#x27;re all valid, all
in a blink of an eye. No browsers required. For people who&#x27;re looking to reduce
the amount of runtime issues in their websites: this is by far the most feasible
way to actually get the number of HTML bugs down to zero.&lt;&#x2F;p&gt;
&lt;p&gt;This isn&#x27;t the first time I&#x27;m writing about this: I &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;yoshuawuyts&#x2F;status&#x2F;1055733604872060928&quot;&gt;first
pitched this in 2019&lt;&#x2F;a&gt; because I didn&#x27;t have the bandwidth to implement it
myself. But Bodil did, who ran with it and subsequently published the
&lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;typed-html&quot;&gt;&lt;code&gt;typed-html&lt;&#x2F;code&gt; crate&lt;&#x2F;a&gt;. This is good; I&#x27;d love to see different approaches of this
same idea spring up in Rust and in other languages. All that&#x27;s needed to get started
is an idea of what the resulting API should look like. And then write a compiler
which takes &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jsdom&#x2F;jsdom&#x2F;tree&#x2F;79c351bc5a5904c1a7ba86414480e0875f53e9cb&#x2F;lib&#x2F;jsdom&#x2F;living&#x2F;nodes&quot;&gt;&lt;code&gt;.webidl&lt;&#x2F;code&gt; node definitions&lt;&#x2F;a&gt;, and outputs types in the right
shape on the other end &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#w3c&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;w3c&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;It&#x27;d be amazing if the W3C kept a repo with these definitions up to
date themselves, so everyone else could just pull them in. But one can wish.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;type-safe-semantic-represenation&quot;&gt;Type-Safe Semantic Represenation&lt;&#x2F;h2&gt;
&lt;p&gt;Once you have a base of checked HTML types that&#x27;s pretty good. But that doesn&#x27;t
mean we&#x27;re quite done yet. Remember when I said we weren&#x27;t getting into ARIA
roles? Well, we are now.&lt;&#x2F;p&gt;
&lt;p&gt;So see, if HTML is &lt;em&gt;structure&lt;&#x2F;em&gt;, and CSS is &lt;em&gt;representation&lt;&#x2F;em&gt;, then ARIA is
&quot;semantics&quot;. &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;Accessibility&#x2F;ARIA&#x2F;Roles&quot;&gt;WAI-ARIA&lt;&#x2F;a&gt;, or &quot;ARIA roles&quot; for short, enables you to ascribe meaning to
your structure. When you see a bunch of &lt;code&gt;&amp;lt;li&amp;gt;&lt;&#x2F;code&gt; items in text form, what are you looking at?
Are they tabs? Are they a menu? Are they a dropdown? ARIA roles enable you to
meaningfully distinguish between them. How many of these roles are there? Over
250, and they all have different properties and interactions.&lt;&#x2F;p&gt;
&lt;p&gt;Again: the path away from trouble here is by creating abstractions. Instead of having
to remember which elements to apply the &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;Accessibility&#x2F;ARIA&#x2F;Roles&#x2F;tablist_role&quot;&gt;&lt;code&gt;tablist&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;Accessibility&#x2F;ARIA&#x2F;Roles&#x2F;tab_role&quot;&gt;&lt;code&gt;tab&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;Accessibility&#x2F;ARIA&#x2F;Roles&#x2F;tabpanel_role&quot;&gt;&lt;code&gt;tabpanel&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
roles on, you should be able to create something akin to Swift&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;documentation&#x2F;swiftui&#x2F;tabview&quot;&gt;&lt;code&gt;TabView&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
which encapsulates all of those differences for you.&lt;&#x2F;p&gt;
&lt;p&gt;This is a higher level of abstraction than just typed HTML provides. But it&#x27;s
equally important, since it&#x27;s a requirement for useful keyboard navigation and
accessibility. It&#x27;ll take some more work than just plain typed HTML, and some
more design work is required to incorparate best practices on how to actually
structure elements since you can&#x27;t just scrape a spec for definitions. But once
you can reason about e.g. &quot;tabs&quot; or &quot;feeds&quot;, building more complex things
becomes a lot easier. Check out the &lt;a href=&quot;https:&#x2F;&#x2F;www.w3.org&#x2F;WAI&#x2F;ARIA&#x2F;apg&#x2F;patterns&#x2F;&quot;&gt;ARIA Patterns
page&lt;&#x2F;a&gt; to get a sense of the kind of
stuff this could cover.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;embracing-compilation&quot;&gt;Embracing Compilation&lt;&#x2F;h2&gt;
&lt;p&gt;To recap so far: we&#x27;ve established that HTML and ARIA are &lt;em&gt;complex&lt;&#x2F;em&gt; interfaces, that
checking during compilation rather than at runtime has a lot of benefits, and
that applying this to ARIA it would enable us to reason about elements at a
higher level of abstraction.&lt;&#x2F;p&gt;
&lt;p&gt;I believe that in order to make this all make the most sense, the web is missing
&quot;sourcemaps for HTML&quot;. If we&#x27;re going to be compiling a bunch of semantic
components down to HTML, then devtools should enable us to reason about them &lt;em&gt;as
components&lt;&#x2F;em&gt;. When inspecting HTML in the DOM, we shouldn&#x27;t have to look at a
bunch of &lt;code&gt;&amp;lt;div&amp;gt;&lt;&#x2F;code&gt;, &lt;code&gt;&amp;lt;p&amp;gt;&lt;&#x2F;code&gt;, and &lt;code&gt;&amp;lt;span&amp;gt;&lt;&#x2F;code&gt; tags. But more meaningful things, such as
&lt;code&gt;&amp;lt;feed&amp;gt;&lt;&#x2F;code&gt;, &lt;code&gt;&amp;lt;profile&amp;gt;&lt;&#x2F;code&gt;, and &lt;code&gt;&amp;lt;calendar&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The way I think this is that devtools are like having access to a debugger. When
debugging a compiled program we usually don&#x27;t reason in terms of &lt;code&gt;MOV rax jax&lt;&#x2F;code&gt; and
&lt;code&gt;POWF bonk donk&lt;&#x2F;code&gt;. But the operations we actually wrote such as: &lt;code&gt;pet_cat&lt;&#x2F;code&gt;, and
&lt;code&gt;big_stretch&lt;&#x2F;code&gt;. It&#x27;s relatively infrequently that actual output is what we&#x27;re
interested in, but it&#x27;s always there if you need it.&lt;&#x2F;p&gt;
&lt;p&gt;Some of you web heads might be wondering: &lt;em&gt;&quot;What about Web Components? - Isn&#x27;t
that the same?&quot;&lt;&#x2F;em&gt; And, like, kind of! It&#x27;s similar in how a reflection in a
mirror is similar to the thing it reflects: similar at first sight, but actually
everything is the opposite.&lt;&#x2F;p&gt;
&lt;p&gt;The point of the Custom Elements part of Web Components is that you can send
&lt;code&gt;&amp;lt;custom-tags&amp;gt;&lt;&#x2F;code&gt; to the browser which are then interpreted at runtime to
introduce interactivity, but preserve qualities such as cacheability of shared
resources. A canonical example here is the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;github&#x2F;relative-time-element&quot;&gt;&lt;code&gt;relative-time-element&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; tag used by
GitHub. What we&#x27;re doing is the opposite: the HTML we send to the browser is
already fully expanded, and doesn&#x27;t need to interpret any JS to enable interactivity.
What we want is for the browser to be able to interpret all of our &lt;code&gt;&amp;lt;li&amp;gt;&lt;&#x2F;code&gt; and
&lt;code&gt;&amp;lt;span&amp;gt;&lt;&#x2F;code&gt; tags generated by our components as the &lt;code&gt;&amp;lt;calendar&amp;gt;&lt;&#x2F;code&gt; and &lt;code&gt;&amp;lt;feed&amp;gt;&lt;&#x2F;code&gt;
elements that we&#x27;ve authored. This is much closer to source maps: associate
the building blocks we generated with the semantic components they actually came from.&lt;&#x2F;p&gt;
&lt;p&gt;The similarity with custom elements comes back up when we take a look at
how custom-elements are rendered in the browser&#x27;s Elements tab:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;html&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-html &quot;&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;relative-time
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;tense&lt;&#x2F;span&gt;&lt;span&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;past&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;datetime&lt;&#x2F;span&gt;&lt;span&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;2016-11-23T11:12:43-08:00&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;data-view-component&lt;&#x2F;span&gt;&lt;span&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;title&lt;&#x2F;span&gt;&lt;span&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Nov 23, 2016, 8:12 PM GMT+1&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    #shadow-root (open)
&lt;&#x2F;span&gt;&lt;span&gt;        &amp;quot;6 years ago&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    November 23, 2016 11:12
&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;relative-time&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This contains all the information anyone needs to debug the element. And what
I&#x27;d love is to be able to access this view for server-rendered components
without ever needing to go use any JS. And the uses don&#x27;t stop there either:
frameworks such as React also reason in terms of components and require &lt;a href=&quot;https:&#x2F;&#x2F;www.npmjs.com&#x2F;package&#x2F;react-devtools&quot;&gt;custom
devtools&lt;&#x2F;a&gt; to re-surface that view. What we really need is a way
to ascribe semantic meaning to our elements in a way that works for both server-
and client-side applications.&lt;&#x2F;p&gt;
&lt;p&gt;Now, it could be that I&#x27;ve missed a capability that would enable doing
&lt;em&gt;exactly&lt;&#x2F;em&gt; this with custom elements in browsers today - or perhaps some other
mechanism. It&#x27;s been a minute since I last used custom elements. But if that&#x27;s
the case I&#x27;d love to learn about it, because in my opinion every framework under
the sun should start making use of that. I know I will!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve talked about the complexity of getting HTML right, how using
a compiler could be used to mitigate those issues, what ARIA roles are, how we
could model higher-level type-safe components, and finally what&#x27;s missing in the
browsers devtools to round this out.&lt;&#x2F;p&gt;
&lt;p&gt;I strongly believe that type-safety would be a boon for the browser space.
People have already experienced some of it with the adoption of TypeScript, and
I believe leaning further into types and type-safety would enable the web
platform to become far more accessible - both for developers and users.&lt;&#x2F;p&gt;
&lt;p&gt;The only piece we can&#x27;t directly control is the ability to teach browsers to
reason about the semantic meaning of elements - almost like being able to
declare source maps for the resulting HTML. In an alternate universe this is
what &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;Web_Components&#x2F;Using_custom_elements&quot;&gt;Custom Elements&lt;&#x2F;a&gt; would have been. But I believe in order to make the web
platform more accessible, we must make it possible to actually reason about
&lt;code&gt;&amp;lt;feed&amp;gt;&lt;&#x2F;code&gt; and &lt;code&gt;&amp;lt;calendar&amp;gt;&lt;&#x2F;code&gt; as first-class items. And not just the &lt;code&gt;&amp;lt;div&amp;gt;&lt;&#x2F;code&gt; and
&lt;code&gt;&amp;lt;p&amp;gt;&lt;&#x2F;code&gt; tags they&#x27;re comprised of.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;update (2023-04-07):&lt;&#x2F;strong&gt; As coincidence will have it, two weeks after publishing
this post the &lt;a href=&quot;https:&#x2F;&#x2F;developer.chrome.com&#x2F;articles&#x2F;declarative-shadow-dom&#x2F;&quot;&gt;chrome&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;webkit.org&#x2F;blog&#x2F;13851&#x2F;declarative-shadow-dom&#x2F;&quot;&gt;safari&lt;&#x2F;a&gt; teams
began discussing the upcoming &quot;declarative shadow DOM&quot; feature.
This seems like it will resolve the outstanding issues involving shipping semantically meaningful elements
from the server.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;update (2023-04-11):&lt;&#x2F;strong&gt; I published the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;html&quot;&gt;&lt;code&gt;html&lt;&#x2F;code&gt; crate&lt;&#x2F;a&gt;
implementing most of this blog post. You can find the source on my GitHub at
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yoshuawuyts&#x2F;html&quot;&gt;yoshuawuyts&#x2F;html&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Capability-Safety I: Prelude</title>
            <pubDate>Tue, 24 Jan 2023 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/capabilities-1/</link>
            <guid>https://blog.yoshuawuyts.com/capabilities-1/</guid>
            <description>&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;In 2021 Tmandry published the post: &lt;a href=&quot;https:&#x2F;&#x2F;tmandry.gitlab.io&#x2F;blog&#x2F;posts&#x2F;2021-12-21-context-capabilities&#x2F;&quot;&gt;&quot;Contexts and Capabilities&quot;&lt;&#x2F;a&gt;.
In it they present the idea of &lt;code&gt;with&lt;&#x2F;code&gt;-clauses, providing a means of passing types such as allocators around in a more
convenient way. The post goes into detail about the feature, but you can
roughly think of it as a way to declare types which are live within a certain
scope, and are automatically passed into functions which require them:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! A usage-only example of `with`-clauses to create scoped allocators.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! This example is somewhat incomplete, but hopefully gives enough of a sense
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! of what it would feel like to use `with`-clauses.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Before: using `#[feature(allocator_api)]` to allocate into a bump allocator.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; bump = bumpalo::Bump::new(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create a bump allocator
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; vec1 = Vec::new_in(&amp;amp;bump);   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Use `new_in` to allocate into the bump allocator
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; vec2 = Vec::new_in(&amp;amp;bump);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; After: using `with`-clauses to allocate into a bump allocator.
&lt;&#x2F;span&gt;&lt;span&gt;with std::alloc::alloc = bumpalo::Bump::new() { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create a bump allocator for this scope
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; vec1 = Vec::new(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `new` uses whichever allocator is currently active
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; vec2 = Vec::new();
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;capability-safety&quot;&gt;Capability-Safety&lt;&#x2F;h2&gt;
&lt;p&gt;While we were brainstorming about &lt;code&gt;with&lt;&#x2F;code&gt;-clauses it got me wondering: Would it be possible to not
only leverage &lt;code&gt;with&lt;&#x2F;code&gt;-clauses as a means of just passing arguments around, but
also as a means of &lt;em&gt;guaranteeing encapsulation&lt;&#x2F;em&gt;?. Or differently put: if we can
think of &lt;code&gt;with&lt;&#x2F;code&gt;-clauses as a way of passing capabilities, would it be possible
for us to make Rust &quot;capability-safe&quot; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#explainer&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;? I reached out to
&lt;a href=&quot;https:&#x2F;&#x2F;hachyderm.io&#x2F;@sunfish&quot;&gt;Sunfishcode&lt;&#x2F;a&gt; who has worked a lot on capabilities for WebAssembly, and for
the past year or so we&#x27;ve been researching how we might be able to introduce
a notion of capability-safety into Rust.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;explainer&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;I&#x27;m intentionally not really going into detail about what
&quot;capability-safety&quot; is exactly; a follow-up to this post is being written. But
to not leave people entirely in the dark, let me
try and summarize it: What if we had access to a kind of function which
guarantees it will only ever operate over &lt;em&gt;exactly&lt;&#x2F;em&gt; what it declared in its
function signature and nothing else. This enables functions to not only
describe what they &lt;em&gt;can&lt;&#x2F;em&gt; do, but by omission now also what they &lt;em&gt;can&#x27;t&lt;&#x2F;em&gt; do.
A lot of safety-critical systems would love to have access to that kind
of expressiveness, but there are a bunch of other uses for it too. This
intersects with a bunch of different aspects of the language, so expect us to go
into minute detail about how we believe we can make this all work in future posts.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;The good news is: we think we have a plausible design - one which not only
enable capability-safety, but crucially would so without breaking any of Rust&#x27;s
stability guarantees. We&#x27;ve consulted with members of both lang and libs, and
at least from a technical point of view it seems like it could work. But if we ever want to
turn it into a formal Rust language proposal, we not only need
the design to be &lt;em&gt;plausible&lt;&#x2F;em&gt;, we also need to show that it&#x27;s something which is &lt;em&gt;beneficial&lt;&#x2F;em&gt;.
Something which solves real issues people experience, and something which people
would be excited to adopt.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-plan&quot;&gt;The plan&lt;&#x2F;h2&gt;
&lt;p&gt;You can consider this post a statement of intent. Sunfish and I are committed to
figuring out how we can actually talk about capability-safety in a way that
makes sense. I&#x27;ve tried and failed to write something coherent post about this a
couple of times now. But we believe it&#x27;s time to actually start publishing about
this. So that&#x27;s exactly what we&#x27;ll be doing!&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ll start explaining by what capabilities are, why they&#x27;re
useful, what capability-safety is, which guarantees it provides, introduce you
to our design, and then work through the various interactions. There&#x27;s not a lot of
material on capability-safety available, so the real challenge for us is to
figure out the right framing and examples to have it actually make sense.&lt;&#x2F;p&gt;
&lt;p&gt;But we&#x27;re convinced we can actually make it happen. Sunfish has already started
writing about some these topics which you can check out here:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;no-ghosts&#x2F;&quot;&gt;No ghosts!&lt;&#x2F;a&gt; (2022-03-15)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;what-is-a-capability&#x2F;&quot;&gt;What is a capability?&lt;&#x2F;a&gt; (2022-11-21)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;His next post will be about capability-safety. Stay tuned for that!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;hachyderm.io&#x2F;@sunfish&quot;&gt;Sunfishcode&lt;&#x2F;a&gt; for help reviewing this post!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>domain-specific error macros</title>
            <pubDate>Tue, 17 Jan 2023 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/ensure-macros/</link>
            <guid>https://blog.yoshuawuyts.com/ensure-macros/</guid>
            <description>&lt;p&gt;When I write custom errors in a project, I also like to write a few small error
macros to accompany them. In my opinion this can make error handling just a
little nicer to use. In this post I briefly want to talk about domain-specific
error macros such as &lt;code&gt;ensure!&lt;&#x2F;code&gt;, what they&#x27;re useful for, and the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;io-ensure&quot;&gt;&lt;code&gt;io-ensure&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
prototype crate I&#x27;ve written which I&#x27;m propose for inclusion in the stdlib next
time I get the chance.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-ensure&quot;&gt;What is ensure?&lt;&#x2F;h2&gt;
&lt;p&gt;If you use Rust you&#x27;re probably familiar with
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;macro.assert.html&quot;&gt;&lt;code&gt;assert!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;: it checks a
condition, and if the condition doesn&#x27;t match it panics. This often looks
something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; condition = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;assert!(condition, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;numbers should equal themselves&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This works well if you&#x27;re writing tests, or validating invariants - but when
you&#x27;re validating input at runtime, instead of panicking you usually probably
want to return errors instead. And the error equivalent to &lt;code&gt;assert!&lt;&#x2F;code&gt; is
&lt;code&gt;ensure!&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;validate_buffet&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; io::Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    ensure!(s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;starts_with&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;tuna&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;), &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;the first course on the cat menu should be tuna&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When discussing &quot;ensure-style macros&quot;, these are typically the ones included:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;format_err!&lt;&#x2F;code&gt;: construct a new instance of an error using a format string&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;bail!&lt;&#x2F;code&gt;: unconditionally create and return an error&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ensure!&lt;&#x2F;code&gt;: create and return an error if the condition doesn&#x27;t match&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ensure_eq!&lt;&#x2F;code&gt;: create and return an error if two expressions don&#x27;t match&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ensure_ne!&lt;&#x2F;code&gt;: create and return an error if two expressions match&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;code&gt;bail&lt;&#x2F;code&gt; is kind of like &lt;code&gt;panic&lt;&#x2F;code&gt;, and &lt;code&gt;ensure&lt;&#x2F;code&gt; is kind of like &lt;code&gt;assert&lt;&#x2F;code&gt;. You can&#x27;t
really construct and pass around panics, so there is no panic-equivalent to
&lt;code&gt;format_err&lt;&#x2F;code&gt;. Also for simplicity I&#x27;m omitting &lt;code&gt;matches&lt;&#x2F;code&gt; variants, and errors
probably shouldn&#x27;t be debug-only, so no &lt;code&gt;debug&lt;&#x2F;code&gt; variants either.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pairing-errors-with-macros&quot;&gt;Pairing errors with macros&lt;&#x2F;h2&gt;
&lt;p&gt;I believe it&#x27;s good practice that if you&#x27;re defining your own errors, to also
define your own error handling macros. Especially if it&#x27;s intended to be
extended by third parties, it can make it significantly nicer to work with.&lt;&#x2F;p&gt;
&lt;p&gt;The key here is that you can use &lt;code&gt;ensure!&lt;&#x2F;code&gt; macros to encode domain-specific
logic with. Say you&#x27;re writing an HTTP framework, you probably want all of your
errors to include an HTTP status code. While if we&#x27;re dealing with IO, we
probably want to map back the underlying OS reason:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Example using `http_types::ensure!`
&lt;&#x2F;span&gt;&lt;span&gt;ensure!(user.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;may_access&lt;&#x2F;span&gt;&lt;span&gt;(resource), StatusCode::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;403&lt;&#x2F;span&gt;&lt;span&gt;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;user is not authorized to access {resource}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Example using `io-ensure`
&lt;&#x2F;span&gt;&lt;span&gt;ensure_eq!(a, b, ErrorKind::Interrupted, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;we are testing the values {} and {} are equal&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, a, b);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;new-keywords&quot;&gt;new keywords&lt;&#x2F;h2&gt;
&lt;p&gt;Work is happening in Rust on creating new language features to reason about
errors. &lt;a href=&quot;https:&#x2F;&#x2F;areweyeetyet.rs&#x2F;&quot;&gt;areweyeetyet&lt;&#x2F;a&gt; provides an overview of this,
but the tldr is that we want to have a way to define &quot;fallible functions&quot; from
which you can &quot;throw&quot; errors. Also: no more &lt;code&gt;Ok(())&lt;&#x2F;code&gt; at the end of every
function.&lt;&#x2F;p&gt;
&lt;p&gt;Having access to a &lt;code&gt;throw&lt;&#x2F;code&gt; (or &lt;code&gt;yeet&lt;&#x2F;code&gt;) keyword means we&#x27;ll have a canonical way
of returning an error from a function. &lt;code&gt;?&lt;&#x2F;code&gt; to re-throw errors, &lt;code&gt;throw&lt;&#x2F;code&gt; to throw
new ones &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#throw-swift&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. But the &lt;code&gt;bail&lt;&#x2F;code&gt; macro  does something very similar
already, and has the downside of having to be defined for every error type:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;throw-swift&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;I&#x27;m using &quot;throw&quot; in the Swift sense of the keyword: &quot;checked
exceptions&quot;. Not the JS&#x2F;Java&#x2F;etc &quot;unchecked exceptions&quot; throwing; I think we all
like our Rust errors to be typed.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; current
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;Err(io::Error::new(e.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;(), format!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{path}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{e}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; using `format_err!`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;Err(io::format_err!(e.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;(), &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{path}:{e}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; using `bail!`
&lt;&#x2F;span&gt;&lt;span&gt;io::bail!(e.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;(), &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{path}:{e}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; if we had `throw` in the language (feature composition!)
&lt;&#x2F;span&gt;&lt;span&gt;throw io::format_err!(e.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;(), &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{path}:{e}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What I&#x27;m thinking here is that it makes sense to include &lt;code&gt;bail&lt;&#x2F;code&gt; if you&#x27;re
writing your own libraries and applications. But probably less for the stdlib,
since whatever goes in there will need to remain stable forever, and having
&lt;code&gt;bail&lt;&#x2F;code&gt; macros + &lt;code&gt;throw&lt;&#x2F;code&gt; keywords is probably a bit too much.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;stdlib&quot;&gt;Stdlib&lt;&#x2F;h2&gt;
&lt;p&gt;So I&#x27;ve written a quick prototype showing: &quot;What if &lt;code&gt;std::io&lt;&#x2F;code&gt; had domain-specific
macros&quot; and published it to crates.io:
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;io-ensure&#x2F;latest&#x2F;io_ensure&#x2F;index.html&quot;&gt;&lt;code&gt;io-ensure&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Is it
great? I&#x27;m not sure. I think it&#x27;s a decent quality of life improvement, and
perhaps it might make sense to include. Just like &lt;code&gt;assert&lt;&#x2F;code&gt; can sometimes make it
easier to work with panics, &lt;code&gt;ensure&lt;&#x2F;code&gt; might sometimes make it easier to work with
errors. Here&#x27;s some random examples of IO error uses I translated from the
&lt;code&gt;rust-lang&#x2F;rust&lt;&#x2F;code&gt; repo:&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;This example omits an extra inline call to &lt;code&gt;format&lt;&#x2F;code&gt;, removing some of the nesting:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; before
&lt;&#x2F;span&gt;&lt;span&gt;fs::create_dir_all(parent).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;e&lt;&#x2F;span&gt;&lt;span&gt;| {
&lt;&#x2F;span&gt;&lt;span&gt;    io::Error::new(
&lt;&#x2F;span&gt;&lt;span&gt;        e.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;        format!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;IO error creating MIR dump directory: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{parent:?}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{e}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;),
&lt;&#x2F;span&gt;&lt;span&gt;    )
&lt;&#x2F;span&gt;&lt;span&gt;})?;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; with io macros
&lt;&#x2F;span&gt;&lt;span&gt;fs::create_dir_all(parent).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;e&lt;&#x2F;span&gt;&lt;span&gt;| {
&lt;&#x2F;span&gt;&lt;span&gt;    io::format_err!(e.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;(), &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;IO error creating MIR dump directory: {parent:?}; {e}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;})?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;blob&#x2F;159ba8a92c9e2fa4121f106176309521f4af87e9&#x2F;compiler&#x2F;rustc_middle&#x2F;src&#x2F;mir&#x2F;pretty.rs#LL232C9-L237C13&quot;&gt;&lt;em&gt;rust&#x2F;compiler&#x2F;rustc_middle&#x2F;src&#x2F;mir&#x2F;pretty.rs&lt;&#x2F;em&gt;&lt;&#x2F;a&gt; ←&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;If &lt;code&gt;librustdoc&lt;&#x2F;code&gt; also had its own error macros, we could imagine we could compose
it with IO error macros like so, saving us from some nesting and branching:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; current
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; nb_errors &amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    Err(Error::new(io::Error::new(io::ErrorKind::Other, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;I&#x2F;O error&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;), &amp;quot;&amp;quot;))
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; with `librustdoc::ensure!` + `io::format_err!`
&lt;&#x2F;span&gt;&lt;span&gt;ensure!(nb_errors &amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, io::format_err!(io::ErrorKind::Other, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;I&#x2F;O error&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;));
&lt;&#x2F;span&gt;&lt;span&gt;Ok(())
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;blob&#x2F;159ba8a92c9e2fa4121f106176309521f4af87e9&#x2F;src&#x2F;librustdoc&#x2F;html&#x2F;render&#x2F;context.rs#L728&quot;&gt;&lt;em&gt;rust&#x2F;src&#x2F;librustdoc&#x2F;html&#x2F;render&#x2F;context.rs&lt;&#x2F;em&gt;&lt;&#x2F;a&gt; ←&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;This call to &lt;code&gt;format&lt;&#x2F;code&gt; with the referencing and subslicing looks rather spicy.
I&#x27;m not super sure what&#x27;s going on there, but presumably we should be able to
avoid it already? Either way, that&#x27;s still an extra inline &lt;code&gt;format&lt;&#x2F;code&gt; call gone:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; current
&lt;&#x2F;span&gt;&lt;span&gt;Err(io::Error::new(
&lt;&#x2F;span&gt;&lt;span&gt;    io::ErrorKind::Uncategorized,
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;amp;format!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;failed to lookup address information: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{detail}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)[..],
&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; with `io::ensure!`
&lt;&#x2F;span&gt;&lt;span&gt;Err(io::format_err!(
&lt;&#x2F;span&gt;&lt;span&gt;    io::ErrorKind::Uncategorized,
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;failed to lookup address information: {detail}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;blob&#x2F;159ba8a92c9e2fa4121f106176309521f4af87e9&#x2F;library&#x2F;std&#x2F;src&#x2F;sys&#x2F;unix&#x2F;net.rs#L55-L58&quot;&gt;&lt;em&gt;rust&#x2F;library&#x2F;std&#x2F;src&#x2F;sys&#x2F;unix&#x2F;net.rs&lt;&#x2F;em&gt;&lt;&#x2F;a&gt; ←&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve talked about domain-specific error macros, what they are,
what they&#x27;re used for, and shown some examples of how they could be used for
&lt;code&gt;io::Error&lt;&#x2F;code&gt; construction in the stdlib.&lt;&#x2F;p&gt;
&lt;p&gt;Overall it&#x27;s just a little convenience pattern which makes working with errors
nicer. Just like &lt;code&gt;assert!&lt;&#x2F;code&gt; is a small quality of life improvement which makes
panics nicer to use; &lt;code&gt;ensure!&lt;&#x2F;code&gt; is a small quality of life improvement which
can make errors nicer to use.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Rust should own its debugger experience</title>
            <pubDate>Thu, 12 Jan 2023 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/rust-should-own-its-debugger-experience/</link>
            <guid>https://blog.yoshuawuyts.com/rust-should-own-its-debugger-experience/</guid>
            <description>&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;2022&#x2F;02&#x2F;15&#x2F;Rust-Survey-2021.html#challenges-ahead&quot;&gt;40% of Rust Developers&lt;&#x2F;a&gt; believe Rust&#x27;s
debugging experience could use improvement. And that&#x27;s not surprising: when we
write code we make assumptions, and sometimes we assume wrong. This leads to
bugs, which we then track down and fix. This is what we call &quot;debugging&quot;, and is a
core part of programming. The purpose-built tools which help us with debugging
are called &quot;debuggers&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Unlike the Rust compiler, the Rust project doesn&#x27;t actually provide a &quot;Rust
debugger&quot;. Users of Rust are instead expected to use a third-party debugger such
as &lt;code&gt;gdb&lt;&#x2F;code&gt;, &lt;code&gt;lldb&lt;&#x2F;code&gt;, or &lt;code&gt;windbg&lt;&#x2F;code&gt; to debug their programs. And support for Rust in
these debuggers is not always &lt;em&gt;great&lt;&#x2F;em&gt;. Basic concepts such as &quot;traits&quot;, &quot;closures&quot;,
and &quot;enums&quot; may have limited support. And debugging async code, or arbitrary
user-defined data structures may be really hard if not impossible. This limits
the utility of debuggers, and in turn limits the Rust user&#x27;s debugging
experience.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;integration-done-right&quot;&gt;Integration done right&lt;&#x2F;h2&gt;
&lt;p&gt;When we interact with the &quot;rust compiler&quot;, it&#x27;s often through either &lt;code&gt;cargo build&lt;&#x2F;code&gt;, or Rust-Analyzer in VSCode &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#vscode&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. The fact that a large chunk of
the compiler is in fact LLVM is for all intents and purposes just an
implementation detail. Even Rust-Analyzer powering the VS Code features is not
something you need to think about most of the time.&lt;&#x2F;p&gt;
&lt;p&gt;This is how it should be. When you install Rust, the right version of LLVM gets
bundled in. The Rust project is responsible for LLVM doing the right things for
Rust, and we&#x27;ll sometimes even float patches on a fork to fix things the project
depends on. Users should never become aware of these details. We&#x27;re even at a
point where we might replace LLVM with a different backend in certain scenarios
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#cranelift&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, and the only thing users should notice are faster build times.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;vscode&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;VS Code has 75% market share apparently. &lt;a href=&quot;https:&#x2F;&#x2F;survey.stackoverflow.co&#x2F;2022&#x2F;#integrated-development-environment&quot;&gt;(src)&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;cranelift&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;I&#x27;m talking about Cranelift for debug builds here.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;debuggers-today&quot;&gt;Debuggers today&lt;&#x2F;h2&gt;
&lt;p&gt;Debuggers have a very different story today. The Rust project doesn&#x27;t really
provide a &quot;debug workflow&quot;, meaning Rust users are made largely responsible for
figuring that out themselves. This means they need to find a debugger, install
it, and figure out how to run it. Whatever Rust support the debugger has is what
they get. And hopefully Rust is enough on debugger author&#x27;s radars that support
for it improves over time. It&#x27;s another question when newer versions of a
debugger may become available to Rust users too.  As a project we can contribute
some patches, but at a fundamental level we don&#x27;t have any &lt;em&gt;control&lt;&#x2F;em&gt; over these
tools. Which means we don&#x27;t have any control over the resulting user experience.&lt;&#x2F;p&gt;
&lt;p&gt;Work is happening though to enable the output of the Rust compiler to be better
understood by third-party debuggers. For example &lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rfcs&#x2F;3191-debugger-visualizer.html&quot;&gt;RFC 3191: Debugger
Visualizer&lt;&#x2F;a&gt; has been accepted which enables Rust users to author
debugger-specific visualizer scripts. This enables library authors to
define debugger-specific scripts which can provide more details about types.
This is a very pragmatic fix which will enable, say, the stdlib to immediately
start providing a better UX for existing debuggers. But we can&#x27;t reasonably
expect all Rust projects to define debugger visualizations for all of their data
structures, so as a general solution it has some pretty clear limitations.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;towards-a-coherent-experience&quot;&gt;Towards a coherent experience&lt;&#x2F;h2&gt;
&lt;p&gt;In my opinion the Rust project needs to rethink its relationship to the debugger
user experience. Rather than something that we leave up to users to figure out,
it should be something that the Rust project is in charge of providing to Rust
users. If we want the Rust debugging experience to improve, we in the project
need to be the ones responsible for providing that experience.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m not suggesting that we start writing debuggers from scratch. Instead I&#x27;m
suggesting we start packaging and distributing existing debuggers for all
platforms, together with plugins which extend those debuggers with Rust-specific
functionality. This will enable us to teach those debuggers about things like
traits, enums, and even async &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#async-details&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. And we can ensure that the debuggers +
plugins are updated regularly, and work correctly. Just like with LLVM, the
specific debugger should become just an implementation detail.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;async-details&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;We can work on ways to extend this to work with ecosystem
runtimes as well.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Which debuggers to package &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#bindings&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, and how to distribute them are details
I&#x27;m confident we can figure out. We&#x27;ve done this before for other tools, so that
shouldn&#x27;t be too different. The main question is how to expose the debugger, and
for that I would propose we start with the &lt;a href=&quot;https:&#x2F;&#x2F;microsoft.github.io&#x2F;debug-adapter-protocol&#x2F;&quot;&gt;Debug Adapter Protocol (DAP)&lt;&#x2F;a&gt;,
LSP&#x27;s less-famous sibling. Just like we use LSP to provide IDE features in an
IDE-agnostic way, we can use DAP to provide debugger support in an IDE-agnostic
way.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;bindings&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;Maybe we don&#x27;t even want to package certain platform-specific
debuggers, and instead we just want to distribute bindings. Maybe different
platforms should make different decisions. Or perhaps people should be able to
choose. These are the kinds of details I expect experts to want to weigh in on.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;I believe by exposing the debugger as a server, we can enable others to
write tooling for it. For example: we could write standalone VSCode extensions which integrate
with it, or perhaps contribute a DAP integration directly to Rust-Analyzer
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#experts&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.  Perhaps some people prefer an editor-based debugger flow; which
should be possible to build against DAP. And should DAP provide limitations, we
can always write extensions with the intent to later upstream them - which is
again something we do with LSP as well.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;experts&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;I defer to the Rust-Analyzer team to comment on what the best course
of action here might be.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;A really interesting idea in the Rust debugger space has been the approach of plugging
a MIR interpreter into a debugger as an extension, which is then able to evaluate
&lt;code&gt;Debug&lt;&#x2F;code&gt; impls at runtime. This has been &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;pull&#x2F;3191#issuecomment-1148714153&quot;&gt;prototyped&lt;&#x2F;a&gt; and
shown to be possible. In my opinion that&#x27;s the ideal solution because it
doesn&#x27;t require any user code to be changed, and it&#x27;s also exactly the kind of
thing that the Rust project can do which external debugger projects can&#x27;t. Just
write your &lt;code&gt;Debug&lt;&#x2F;code&gt; impls, and the debugger will figure out how to interpret
them.  Making this practical will not be without challenges, but those are
mostly technical - and technical talent is something we&#x27;re not short on in the
Rust project.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Those are my thoughts on how I think we can structurally improve the debugging
user experience in Rust. I believe that by making the Rust project responsible
for the debugger experience we can provide a fundamentally better experience
than any external debuggers ever could. And I would be excited if this was
something the &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;rust-should-own-its-debugger-experience&#x2F;%5Bhttps:&#x2F;&#x2F;rust-lang.github.io&#x2F;compiler-team&#x2F;working-groups&#x2F;debugging&#x2F;%5D&quot;&gt;Debugging WG&lt;&#x2F;a&gt; would seek to pursue.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;One last note before publishing: Debugger extensions in VS Code also have
support for profiling and even &lt;a href=&quot;https:&#x2F;&#x2F;code.visualstudio.com&#x2F;Docs&#x2F;editor&#x2F;debugging#_debug-console-repl&quot;&gt;REPL-like evaluation&lt;&#x2F;a&gt;. I think this is
part of DAP too, or some extension to it at least. I feel very similar about
profiling like I do about debugging: the Rust project should be responsible for
providing a premier user experience. But we have to start somewhere, and I think
if we can build the integrations needed to support debugging, we can eventually
grow the scope to become responsible for profiling too. &lt;a href=&quot;https:&#x2F;&#x2F;go.dev&#x2F;blog&#x2F;pprof&quot;&gt;Go&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;code.visualstudio.com&#x2F;docs&#x2F;nodejs&#x2F;profiling&quot;&gt;JS&lt;&#x2F;a&gt; have this
already, and I&#x27;d love for Rust to catch up.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;michaelwoerister&quot;&gt;Michael Woerister&lt;&#x2F;a&gt; for reviewing!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>State Machines III: Type States</title>
            <pubDate>Mon, 02 Jan 2023 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/state-machines-3/</link>
            <guid>https://blog.yoshuawuyts.com/state-machines-3/</guid>
            <description>&lt;p&gt;I&#x27;ve been writing a bit about state machines recently. In my last post I
explained how we could potentially leverage arbitrary self-types and anonymous
enums to support type-level state machines as a first-class construct. Which is
cool, but it had some readers asking: &lt;em&gt;&quot;How does this improve on the existing
type state pattern?&quot;&lt;&#x2F;em&gt; Which is fair!&lt;&#x2F;p&gt;
&lt;p&gt;Well, to start off by answering that question: it&#x27;s only after authoring that
post that I learned that &quot;type states&quot; have a name! I was familiar with the
pattern, but I didn&#x27;t realize it had a name. If you&#x27;d like to learn more about
them, &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=bnnacleqg6k&quot;&gt;Will Chrichton gave an excellent presentation about API design which also
covers type states&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Though type states are powerful, they&#x27;re not the easiest to use - and can be
limited in expressivity at times. In this post I want to show what some of those
limitations are, and how we can over come them by encoding them using
first-class type-level state machines instead.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;editor&#x27;s note: I tried capping this post off at 500 words and failed. I&#x27;m
sorry, here&#x27;s 2500 words instead.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;setting-the-stage&quot;&gt;Setting the stage&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;ll continue using the example we&#x27;ve been using in the past two posts; a
traffic light which can transition between states. We&#x27;ll take the simpler
variant of that for this post:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;green can transition to yellow&lt;&#x2F;li&gt;
&lt;li&gt;yellow can transition to red&lt;&#x2F;li&gt;
&lt;li&gt;red can transition to green&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If we want to encode it with the type-state pattern, we have to create separate
structs for each of the states, and then parameterize the traffic light struct
over the state. This is roughly what that looks like
(&lt;a href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=stable&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=89817f14b28a0abb053bd23c2865b086&quot;&gt;playground&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::marker::PhantomData;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Green;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Yellow;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Red;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;TrafficLight&amp;lt;S&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;_phantom&lt;&#x2F;span&gt;&lt;span&gt;: PhantomData&amp;lt;S&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;TrafficLight&amp;lt;Green&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; TrafficLight&amp;lt;Green&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        TrafficLight { _phantom: PhantomData }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;TrafficLight&amp;lt;Green&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; TrafficLight&amp;lt;Yellow&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        TrafficLight { _phantom: PhantomData }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;TrafficLight&amp;lt;Yellow&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; TrafficLight&amp;lt;Red&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        TrafficLight { _phantom: PhantomData }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;TrafficLight&amp;lt;Red&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; TrafficLight&amp;lt;Green&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        TrafficLight { _phantom: PhantomData }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; light = TrafficLight::new(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; TrafficLight&amp;lt;Green&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; light = light.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; TrafficLight&amp;lt;Yellow&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; light = light.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; TrafficLight&amp;lt;Red&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; light = light.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; TrafficLight&amp;lt;Green&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This makes it so that if we attempt to call &lt;code&gt;to_red&lt;&#x2F;code&gt; when we have a
&lt;code&gt;TrafficLight&amp;lt;Green&amp;gt;&lt;&#x2F;code&gt;, the compiler will disallow it. Type states allow us to
encode program invariants into the type system, preventing it from causing
runtime bugs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;where-type-states-run-into-trouble&quot;&gt;Where type states run into trouble&lt;&#x2F;h2&gt;
&lt;p&gt;Type states become tricky when you start wanting to combine them with runtime
logic. After all, a traffic light example is nice: but what if we&#x27;re actually
trying to run it? Take for example the following code, which can&#x27;t be neatly
represented using type states:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_lite::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_time::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_time::time::Duration;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_time::stream;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; light = TrafficLight::new();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; interval = stream::interval(Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(_) = interval.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().await {
&lt;&#x2F;span&gt;&lt;span&gt;    light = light.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Cycle to the next state every 20ms
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We want to switch to the next &lt;code&gt;state&lt;&#x2F;code&gt; every 20s, but this won&#x27;t compile because
&lt;code&gt;TrafficLight&amp;lt;Green&amp;gt;&lt;&#x2F;code&gt; and &lt;code&gt;TrafficLight&amp;lt;Yellow&amp;gt;&lt;&#x2F;code&gt; aren&#x27;t the same type, so they
can&#x27;t be re-assigned to the same value. In order to do so we can match the
type states back to an actual enum, and wrap the type-state variant in it. This
could look something like this (&lt;a href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=stable&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=9ee7d3be89271befc809b1b2ab6e21af&quot;&gt;playground&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_lite::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_time::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_time::time::Duration;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_time::stream;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;TrafficLightWrapper {
&lt;&#x2F;span&gt;&lt;span&gt;    Green(TrafficLight&amp;lt;Green&amp;gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    Yellow(TrafficLight&amp;lt;Yellow&amp;gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    Red(TrafficLight&amp;lt;Red&amp;gt;),
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;TrafficLightWrapper {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        TrafficLightWrapper::Green(TrafficLight::new())
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            TrafficLightWrapper::Green(inner) =&amp;gt; TrafficLightWrapper::Yellow(inner.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;()),
&lt;&#x2F;span&gt;&lt;span&gt;            TrafficLightWrapper::Yellow(inner) =&amp;gt; TrafficLightWrapper::Red(inner.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;()),
&lt;&#x2F;span&gt;&lt;span&gt;            TrafficLightWrapper::Red(inner) =&amp;gt; TrafficLightWrapper::Green(inner.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;()),
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; light = TrafficLightWrapper::new();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; interval = stream::interval(Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(_) = interval.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().await {
&lt;&#x2F;span&gt;&lt;span&gt;    light = light.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a non-trivial amount of boilerplate, just to work with code which uses
the type state pattern at runtime. 50 lines to encode just 3 states is probably
too much to be practical for most uses, even if the resulting API is flexible enough
to be used in a variety of scenarios. We should be able to do better than this!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;doing-better-with-enums&quot;&gt;Doing better with enums&lt;&#x2F;h2&gt;
&lt;p&gt;Now, say we had access to
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;pull&#x2F;1450&quot;&gt;&lt;code&gt;enum-variant-types&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; (enum
variants as first-class types), and
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;44874&quot;&gt;&lt;code&gt;arbitrary-self-types&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, we
could imagine a reformulation of the traffic light as follows:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! A basic traffic light state machine
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Novel language features: enum-variant-types, arbitrary-self-types
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;TrafficLight {
&lt;&#x2F;span&gt;&lt;span&gt;    Green,
&lt;&#x2F;span&gt;&lt;span&gt;    Yellow,
&lt;&#x2F;span&gt;&lt;span&gt;    Red,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;TrafficLight {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Green
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Yellow {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Yellow
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Yellow) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Red {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Red
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Red) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Green
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; light = TrafficLight::new(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; TrafficLight&amp;lt;Green&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    light = light.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; TrafficLight&amp;lt;Yellow&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    light = light.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; TrafficLight&amp;lt;Red&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    light = light.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; TrafficLight&amp;lt;Green&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Because &lt;code&gt;TrafficLight&lt;&#x2F;code&gt; is now a single type, it can be assigned to the same
variable without a problem. Paving over some details, we could imagine the
following could then work as well:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ..imports..
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; light = TrafficLight::new();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; interval = stream::interval(Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(_) = interval.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().await {
&lt;&#x2F;span&gt;&lt;span&gt;    light = light.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Cycle to the next state every 20ms
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And that, in a nutshell, is why I believe that access to first-class state
machines at the type level would be helpful. It would enable us to use type
states in more places, which in turn would allow us to create more robust
abstractions, which yet in turn lead to fewer bugs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;embedding-in-structs&quot;&gt;Embedding in structs&lt;&#x2F;h2&gt;
&lt;p&gt;Being able to treat enums as type-level state machines has other benefits as
well: it makes it so when you embed a state machine in another type, the state
itself doesn&#x27;t necessarily need to be observable from the outside either. Take
the following code:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Green;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Yellow;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Red;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;TrafficLight&amp;lt;S&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;_phantom&lt;&#x2F;span&gt;&lt;span&gt;: PhantomData&amp;lt;S&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; A new struct containing multiple traffic lights
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Crosswalk&amp;lt;S1, S2&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;light1&lt;&#x2F;span&gt;&lt;span&gt;: TrafficLight&amp;lt;S1&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;light2&lt;&#x2F;span&gt;&lt;span&gt;: TrafficLight&amp;lt;S2&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;S1, S2&amp;gt; Crosswalk&amp;lt;S1, S2&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt; async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; loop here.
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The internal states for each of the traffic lights necessarily becomes externally
observable, even if no external methods ever need to observe it. The internal
state &lt;em&gt;leaks&lt;&#x2F;em&gt; to the external API surface, making it a leaky abstraction. We
could of course define the wrapper type we saw earlier again. But say we
did have first-class state machines, we could encode it directly like this instead:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;TrafficLight {
&lt;&#x2F;span&gt;&lt;span&gt;    Green,
&lt;&#x2F;span&gt;&lt;span&gt;    Yellow,
&lt;&#x2F;span&gt;&lt;span&gt;    Red,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; A new struct containing multiple traffic lights
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Crosswalk {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;light1&lt;&#x2F;span&gt;&lt;span&gt;: TrafficLight,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;light2&lt;&#x2F;span&gt;&lt;span&gt;: TrafficLight,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;CrossWalk {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt; async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; loop here.
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We could still choose to surface the enums to the outside world if we wanted to
(more on that later in this post). But there is a real benefit to not having to
if you don&#x27;t want to, without needing to define pages of boiletplate!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;enum-method-unification&quot;&gt;Enum method unification&lt;&#x2F;h2&gt;
&lt;p&gt;One assumption I&#x27;ve made is that if you have an enum with three states, and you
define a method for all three states, then that method should become available
even if we don&#x27;t know which state we&#x27;re in.&lt;&#x2F;p&gt;
&lt;p&gt;Using &lt;code&gt;match&lt;&#x2F;code&gt; we can always find out what state we&#x27;re in by inspecting the
enum&#x27;s tag, meaning we can always figure out what state we&#x27;re in and what state
we should transition to, at runtime.&lt;&#x2F;p&gt;
&lt;p&gt;This also means that, say, if a method is only available for 2&#x2F;3 of the states,
as long as we can &lt;code&gt;match&lt;&#x2F;code&gt; down to those states, the method should be available:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;RGB { Red, Green, Blue }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;RGB {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;test&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Blue) {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;can print!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;try_to_print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;rgb&lt;&#x2F;span&gt;&lt;span&gt;: RGB) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; rgb {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;RGB&lt;&#x2F;span&gt;&lt;span&gt;::Green | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;RGB&lt;&#x2F;span&gt;&lt;span&gt;::Blue =&amp;gt; rgb.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(),  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `print` is defined for both states here
&lt;&#x2F;span&gt;&lt;span&gt;        _ =&amp;gt; { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;* do nothing *&#x2F; &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;enums-as-type-params&quot;&gt;Enums as type params&lt;&#x2F;h2&gt;
&lt;p&gt;Even if we could hide the internal state sometimes, doesn&#x27;t mean we&#x27;d always
want to do it. I think one other benefit of &quot;enums as state machines&quot; in this
model would be just to improve the existing type-state pattern. Take for example
my &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tasky&#x2F;3.0.0&#x2F;tasky&#x2F;index.html&quot;&gt;&lt;code&gt;tasky&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate. In v3.0.0 we
distinguished between a &quot;local builder&quot; and &quot;non-local builder&quot; at the type
level. This was needed so we could add different &lt;code&gt;IntoFuture&lt;&#x2F;code&gt; implementations to
them. This is how they&#x27;re defined:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Sealed trait to determine what type of builder we got.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mod &lt;&#x2F;span&gt;&lt;span&gt;sealed {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Kind {}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A local builder.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Local;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;sealed::Kind &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Local {}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A nonlocal builder.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;NonLocal;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;sealed::Kind &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;NonLocal {}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Task builder that configures the settings of a new task.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Builder&amp;lt;Fut: Future, K: sealed::Kind&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: PhantomData&amp;lt;K&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;future&lt;&#x2F;span&gt;&lt;span&gt;: Fut,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;builder&lt;&#x2F;span&gt;&lt;span&gt;: ...,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s a lot of work to encode the state &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#seal&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. And just from glancing over the
rustdoc output you&#x27;d never know that that&#x27;s what this is for. Instead it&#x27;d be
far nicer if we could define typestates using enums, and not actually have to
bother with sealed traits and disjointed structs:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;seal&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;A note on sealed traits: this is the first time in the post we&#x27;re using
them, but they&#x27;re useful to ensure that only types defined within the crate can
ever be passed to it. If we had support for concrete types in bounds + enums as
first-class types, then we&#x27;d probably have less need for sealed traits to be
used in this way.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;BuilderKind {
&lt;&#x2F;span&gt;&lt;span&gt;    Local,
&lt;&#x2F;span&gt;&lt;span&gt;    NonLocal,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Task builder that configures the settings of a new task.
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Debug)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Builder&amp;lt;Fut: Future, K: BuilderKind&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: K,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;future&lt;&#x2F;span&gt;&lt;span&gt;: Fut,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;builder&lt;&#x2F;span&gt;&lt;span&gt;: ...,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I believe doing this would require us to enable using concrete types as
type-bounds. I believe this is something which comes up repeatedly, and we do
want to resolve eventually for other reasons as well. Perhaps &quot;better
typestates&quot; could be added to that list as well now?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;enum-variant-tracking&quot;&gt;Enum variant tracking&lt;&#x2F;h2&gt;
&lt;p&gt;Another feature which would probably be helpful here would be something I call
&quot;enum variant tracking&quot;. Take for example the following code, which inserts a
value into &lt;code&gt;Option&lt;&#x2F;code&gt; if it doesn&#x27;t exist, and then provides us with mutable
access to it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; option = None;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; option.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_none&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    option = Some(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; num: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut u32 &lt;&#x2F;span&gt;&lt;span&gt;= option.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; may panic
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Sure, &lt;code&gt;Option::unwrap_or_else&lt;&#x2F;code&gt; exists and does the same. But assume for a second
we&#x27;ve defined our own &lt;code&gt;Option&lt;&#x2F;code&gt;, and we need to implement our own. We should
&lt;em&gt;never&lt;&#x2F;em&gt; have to &lt;code&gt;unwrap&lt;&#x2F;code&gt; here, since we know from the code that we&#x27;re
&lt;em&gt;guaranteed&lt;&#x2F;em&gt; to always have a &lt;code&gt;Some&lt;&#x2F;code&gt; variant here. And the &lt;code&gt;is_none&lt;&#x2F;code&gt; check is
redundant here, since we&#x27;re guaranteed to always have a &lt;code&gt;None&lt;&#x2F;code&gt; variant to start
with.&lt;&#x2F;p&gt;
&lt;p&gt;The idea is that if we &lt;em&gt;know&lt;&#x2F;em&gt; for a fact that we&#x27;re dealing with a specific
variant, we should be able to skip the ceremony and checks to access that
specific variant. Instead of just knowing we have an &lt;code&gt;Option&lt;&#x2F;code&gt;, with &quot;enum
variant types&quot; we should be able to accurately track that we in fact start with an
&lt;code&gt;Option::None&lt;&#x2F;code&gt;, which always becomes &lt;code&gt;Option::Some&lt;&#x2F;code&gt; after. The latter might be a
bit more tricky, but given both &lt;code&gt;option&lt;&#x2F;code&gt; and &lt;code&gt;is_some&lt;&#x2F;code&gt; are &lt;code&gt;const&lt;&#x2F;code&gt;, we could
imagine that the compiler should be able to always know this.&lt;&#x2F;p&gt;
&lt;p&gt;To clarify though: while I think this feature might make sense from a
theoretical perspective, it may not make sense from a &lt;em&gt;practical one&lt;&#x2F;em&gt;. I&#x27;m not
trying to argue we should or shouldn&#x27;t support this, more that it might be
within the realm of possibility if we get &quot;enum variant types&quot;. This
feature would also only be intended for local reasoning only. Nothing should
ever cross function boundaries; other features should be available to enable us
to more granularly annotate things. I think if we ever start to get serious
about wanting to allow people to write panic-free code, this may become
interesting. I&#x27;m kind of reminded of the (unstable)
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;result&#x2F;enum.Result.html#method.into_ok&quot;&gt;&lt;code&gt;Error::into_ok&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
method, which is gated behind the &lt;code&gt;unwrap_infallible&lt;&#x2F;code&gt; feature on nightly.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; option = None;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; option.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_none&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    option = Some(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; num: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut u32 &lt;&#x2F;span&gt;&lt;span&gt;= option.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; will never panic
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;narrowing-of-state-modifications&quot;&gt;narrowing of state modifications&lt;&#x2F;h2&gt;
&lt;p&gt;Something we haven&#x27;t yet covered, but probably should is the fact that all the
state transition things we&#x27;ve talked about only work with &lt;em&gt;owned&lt;&#x2F;em&gt; types. They
don&#x27;t at all work with mutable references. When we&#x27;re calling &lt;code&gt;next&lt;&#x2F;code&gt; on an
iterator we get a &lt;code&gt;&amp;amp;mut Self&lt;&#x2F;code&gt; type. When transitioning between state machines,
wouldn&#x27;t it make sense for the state transitions to be able to mutate
&lt;code&gt;Self&lt;&#x2F;code&gt; rather than always having to return a value?&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve saved this one for last, because this is where I really start to hesitate
to be honest. All the features we&#x27;ve covered so far are in my opinion fairly
natural extensions to what we already have. Subsets of enums, being able to use
enums in more places, being able to narrow our views. What we&#x27;re talking about
here feels much further &lt;em&gt;out there&lt;&#x2F;em&gt;, and so I&#x27;m also way less sure whether it&#x27;s a
good idea.&lt;&#x2F;p&gt;
&lt;p&gt;The basic premise is as follows, we want to enable the following to work:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; light = TrafficLight::new(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; TrafficLight&amp;lt;Green&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    light.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; TrafficLight&amp;lt;Yellow&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    light.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; TrafficLight&amp;lt;Red&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    light.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; TrafficLight&amp;lt;Green&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This means we&#x27;d need to find a syntax in the view type to not only describe what
types go in, but also what the type will transition to. Niko&#x27;s view type post
didn&#x27;t cover this, and my previous state machine post didn&#x27;t cover this either.
But at least conceptually, it seems to me that if we would enable a narrowing of
function parameters and function return types, we might also want to provide a
way to express a narrowing of value modifications.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m completely just riffing here, but maybe something like this? This is
supposed to indicate that after the function returns, the value of &lt;code&gt;self&lt;&#x2F;code&gt; will
be &lt;code&gt;Self::Yellow&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;TrafficLight {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Yellow) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Yellow
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I&#x27;m really unsure about this. But I think if we end up doing anonymous enums
and view types, then this might be a question we may want to find an answer for.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;language-feature-overview&quot;&gt;Language feature overview&lt;&#x2F;h2&gt;
&lt;p&gt;To recap: here is the list of language features we&#x27;ve covered in this series so
far. None of them are quite enough to bring us all the way, but if we combine
them they might unlock the ability to improve the status quo of type states:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;enum variant types&lt;&#x2F;strong&gt;: Enable reasoning about enum members as first-class
types. We can&#x27;t specify say that a method returns a specific enum member. We can
only ever return the full enum.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;arbitrary self-types &#x2F; enum view-types&lt;&#x2F;strong&gt;: Enable declaring &lt;code&gt;Self: SomeEnum::Member&lt;&#x2F;code&gt;, allowing us to declare methods which are only available for
certain enum variants.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;anonymous enums &#x2F; enum subsets&lt;&#x2F;strong&gt;: To enable us to declare sub-sets of enums using syntax
like: &lt;code&gt;Member1 | Member2&lt;&#x2F;code&gt;. For example, we may want to declare that a certain
method can only return a specific sub-set of errors, or specific network status codes.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;enum member unification&lt;&#x2F;strong&gt;: Say a method &lt;code&gt;next&lt;&#x2F;code&gt; is declared for
&lt;code&gt;SomeEnum::Blue&lt;&#x2F;code&gt; and &lt;code&gt;SomeEnum::Red&lt;&#x2F;code&gt;. If we obtain &lt;code&gt;Blue | Red&lt;&#x2F;code&gt; then we should
be able to call that method in either case. From the perspective of the language
it should be no different than if we&#x27;d have an enum with just those two members,
and we&#x27;d have the method implemented for that entire enum.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;enum variant tracking&lt;&#x2F;strong&gt;: If we &lt;em&gt;know&lt;&#x2F;em&gt; for a fact that we&#x27;re dealing with a
specific variant, we should be able to skip the ceremony and checks to access
that specific variant.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;narrowing of state modifications&lt;&#x2F;strong&gt;: If we end up with anonymous enums and
view types, we&#x27;ll have syntax to express narrowings of both owned input and
output function params. If that&#x27;s the case, we may also find ourselves wanting
to express narrowings of in-out params, which requires a way to express.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;concrete type bounds&lt;&#x2F;strong&gt;: So we can use &lt;code&gt;where S: SomeEnum::Member&lt;&#x2F;code&gt; directly as a bound,
where &lt;code&gt;State&lt;&#x2F;code&gt; is an enum. Currently using sealed traits + individual structs
seems like the best way to approximate this.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;ve covered quite a number of language features so far. Just to be clear: I&#x27;m
not trying to say that we should be implementing any of this, and even if we
decided to: that we should be prioritizing this. I&#x27;m more interested in thinking
out loud about how we could improve on type states, and summarizing which
language features could be implemented to bring us closer to that.&lt;&#x2F;p&gt;
&lt;p&gt;With that in mind, I hope this made for an interesting read. Thanks for reading,
and happy new year!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;dippedrusk.com&#x2F;&quot;&gt;Vagrant&lt;&#x2F;a&gt; for proof reading this post!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>2022 in review</title>
            <pubDate>Fri, 23 Dec 2022 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/look-back-2022/</link>
            <guid>https://blog.yoshuawuyts.com/look-back-2022/</guid>
            <description>&lt;p&gt;It&#x27;s pretty quiet at work right now, and every other application on my phone is
telling me it&#x27;s time to look back. So why not lean in and look back at the last
12 months. Not some big reflection time, but to share some things I&#x27;ve done and
liked. I&#x27;ve published about a novel&#x27;s worth of work in the past year, and
probably read a multitude of that. So if you&#x27;re looking to read some tech
related things over the holidays, maybe you&#x27;ll find something fun in this list!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;my-own-work&quot;&gt;My own work&lt;&#x2F;h2&gt;
&lt;p&gt;Here are things I&#x27;ve worked on and written about this year:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;rust-language-work&quot;&gt;Rust Language Work&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;inside-rust&#x2F;2022&#x2F;07&#x2F;27&#x2F;keyword-generics.html&quot;&gt;Announcing the Keyword Generics
Initiative&lt;&#x2F;a&gt;:
Where we announce the creation of the &quot;keyword generics initiative&quot;, a new
group under the language team looking to add a new type of generic to the language &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#update&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;more-enum-types&#x2F;&quot;&gt;More Enum Types&lt;&#x2F;a&gt;: We discuss
what potentially the enum-equivalent of tuples and &lt;code&gt;impl trait&lt;&#x2F;code&gt; could look like. This could be useful, for say, easier application error handling.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;state-machines-2&#x2F;&quot;&gt;State Machines II&lt;&#x2F;a&gt;: We take a
look at typestates&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#ast&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;  in Rust, and explore a way to make them a first-class
citizen in Rust by leveraging arbitrary-self-types, enums as first-class
types, and anonymous enums. The biggest innovation here is that we&#x27;d have a
way to prevent them from leaking to enclosing types by using enums instead of generics.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;state-machines-2&#x2F;&quot;&gt;Inline Crates&lt;&#x2F;a&gt;: We discuss
the difference between &quot;crates&quot; and &quot;modules&quot;, and explore what feature parity
between the two could look like, and what challenges enabling that would bring.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;unsafe-syntax&#x2F;&quot;&gt;Keywords I: Unsafe Syntax&lt;&#x2F;a&gt;:
Reflecting on the various meanings of the &lt;code&gt;unsafe&lt;&#x2F;code&gt; keyword in Rust.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;const-syntax&#x2F;&quot;&gt;Keywords II: Const Syntax&lt;&#x2F;a&gt;:
Reflecting on the various meanings of the &lt;code&gt;const&lt;&#x2F;code&gt; keyword in Rust.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;ast&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;I didn&#x27;t know &quot;type states&quot; had a name until after I wrote the post, so
they&#x27;re not mentioned by name in the post.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;update&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;I&#x27;m planning to write an update on the work we&#x27;ve done so far after
the holidays. Stay tuned for that I guess?&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;async-work&quot;&gt;Async Work&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;why-async-rust&#x2F;&quot;&gt;Why Async Rust&lt;&#x2F;a&gt;: In which I
explain what async Rust is, which features it provides, and how we can
meaningfully talk about whether it makes sense to adopt.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;futures-concurrency-3&#x2F;&quot;&gt;Futures Concurrency III:
Select!&lt;&#x2F;a&gt;: A deep-dive into
the async &lt;code&gt;select!&lt;&#x2F;code&gt; macro, discussing its various shortcoming, and looking at
an alternative structured concurrency operator which doesn&#x27;t share these
shortcomings.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;safe-pin-projections-through-view-types&#x2F;&quot;&gt;Safe pin projections through view
types&lt;&#x2F;a&gt;: Goes
into some detail on how we could leverage the &quot;view types&quot; proposal to make
pin projections safe. Not quite a full proposal, but intended to give a first
impression of what this might look like.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;futures-concurrency-4&#x2F;&quot;&gt;Futures Concurrency IV: Join
Ergonomics&lt;&#x2F;a&gt;: We take a
look at Swift&#x27;s &lt;code&gt;async let&lt;&#x2F;code&gt; feature, and how we can enable similar
semantics in Rust&#x27;s libraries using &lt;code&gt;IntoFuture&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;2022&#x2F;09&#x2F;22&#x2F;Rust-1.64.0.html#enhancing-await-with-intofuture&quot;&gt;Enhancing &lt;code&gt;.await&lt;&#x2F;code&gt; with
&lt;code&gt;IntoFuture&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:
The release 1.64 release notes cover the stabilization of &lt;code&gt;IntoFuture&lt;&#x2F;code&gt;, and
show some cool things you can do with it.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-iterator-crate&#x2F;&quot;&gt;Async-Iterator crate&lt;&#x2F;a&gt;: A
short PSA that I tried the unstable &quot;async fn in traits&quot; feature, and
published a crate which makes use of it.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;postfix-spawn&#x2F;&quot;&gt;Postfix Spawn&lt;&#x2F;a&gt;: A first look at
the nature of async Rust&#x27;s &lt;code&gt;spawn&lt;&#x2F;code&gt;-family of APIs, and how we can make them
behave in a structured manner. I wrote this in a fever-dream, and probably
should write a follow-up.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-cancellation-2&#x2F;&quot;&gt;Async Cancellation II: Time and
Signals&lt;&#x2F;a&gt;: A first look at
a newly created suite of time-based APIs, combining concurrency and
cancellation to create a cohesive set of async control flow constructs.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;miscellaneous&quot;&gt;Miscellaneous&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;rust-2023&#x2F;&quot;&gt;Rust 2023&lt;&#x2F;a&gt;: My thoughts and vision
on the Rust project, late 2022 edition.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;other-s-work&quot;&gt;Other&#x27;s work&lt;&#x2F;h2&gt;
&lt;p&gt;Here are things I&#x27;ve read this year which were a highlight for me. Some of it
was published this year, other things are from earlier years. But either way,
these were highlights for me:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;rust&quot;&gt;Rust&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;security.googleblog.com&#x2F;2022&#x2F;12&#x2F;memory-safe-languages-in-android-13.html&quot;&gt;&quot;Memory Safe Languages in Android 13&quot; by Vander
Stoep (Google)&lt;&#x2F;a&gt;:
provides compelling evidence that adopting Rust does in fact meaningfully reduce the number
of memory safety bugs in codebases. And crucially: significantly reduces the
number of high&#x2F;critical vulnerabilities. Imo this is one of the most important
reports written about Rust in recent years.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;marabos.nl&#x2F;atomics&#x2F;&quot;&gt;&quot;Rust Atomics and Locks&quot; by Mara Bos&lt;&#x2F;a&gt;: While
technically not yet published, I did get a chance to read the pre-release version,
and go in-depth on some of the topics in the book with Mara over the past
year. I haven&#x27;t yet finished the book, but I already feel like I understand
atomics so much better now (read: at all), and in my opinion this is a
must-have for everyone looking to go going beyond the basics in Rust.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=bnnacleqg6k&quot;&gt;&quot;Type-Driven API Design in Rust (video)&quot; by Will
Crichton&lt;&#x2F;a&gt;: walks through
designing an API in Rust step-by-step, showing how Rust&#x27;s type system
can be leveraged to guard against increasingly more kinds of invalid uses.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sabrinajewson.org&#x2F;blog&#x2F;async-drop&quot;&gt;&quot;Async destructors, async genericity and completion futures&quot; by Sabrina
Jewson&lt;&#x2F;a&gt;: a foray into the design
challenges of designing an &quot;async Drop&quot; feature in Rust, providing some sharp
insights on the matter. Deep-dives into the design problem space as done at
the start of this post are in my opinion something we need more of in the Rust
project.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;faultlore.com&#x2F;blah&#x2F;tower-of-weakenings&#x2F;&quot;&gt;&quot;The Tower of Weakenings: Memory Models for Everyone&quot; by Aria
Beingessner&lt;&#x2F;a&gt;: Explains what
provenance is, why we should care, and how we can bring strict provenance to
Rust. This is one of those posts which really peels back the cover on the
sticks-and-bubblegum nature we&#x27;re building on, and then proposes a way to
actually fix that without proposing everyone need become an expert in the process.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;capabilities&quot;&gt;Capabilities&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;no-ghosts&#x2F;&quot;&gt;&quot;No Ghosts!&quot; by Sunfishcode&lt;&#x2F;a&gt;:
proposes and explores a design principle for components in complex software
systems.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;what-is-a-capability&#x2F;&quot;&gt;&quot;What is a Capability&quot; by
Sunfishcode&lt;&#x2F;a&gt;: Answers the
question: &quot;What is a capability?&quot;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.cs.cmu.edu&#x2F;~aldrich&#x2F;papers&#x2F;effects-icfem2018.pdf&quot;&gt;&quot;Capabilities: effects for
free&quot; by Craig et al.&lt;&#x2F;a&gt;: bridges
the concept of &quot;capabilities&quot; with &quot;effects&quot;, showing how we can use effects
as capabilities.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.slideshare.net&#x2F;slideshow&#x2F;embed_code&#x2F;key&#x2F;aLE9M37dQdbUFy&quot;&gt;&quot;Capabilities for Resources and Effects&quot; by
Martin Odersky&lt;&#x2F;a&gt;:
The Scala project got a 7-year EU research grant to investigate adding capabilities and
effects into the language. This describes what that work will be focusing on.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;tmandry.gitlab.io&#x2F;blog&#x2F;posts&#x2F;2021-12-21-context-capabilities&#x2F;&quot;&gt;&quot;Contexts and Capabilities in Rust&quot; by Tyler
Mandry&lt;&#x2F;a&gt;:
(I was involved with this), describes the &quot;context problem&quot; in Rust, and
explains how we could solve this by adding a new &quot;with-clause&quot; language feature.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=phodPLY8zNE&quot;&gt;&quot;The Path to Components (video)&quot; by Luke
Wagner&lt;&#x2F;a&gt;: Goes in-depth on the
the WASM component model: what it is, where it&#x27;s currently at, and where it&#x27;s
headed.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;systemic-safety&quot;&gt;Systemic Safety&lt;&#x2F;h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Blaming human error for an outage is like blaming gravity for a building
falling over&quot; — &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;tef_ebooks&#x2F;status&#x2F;1284453954462588930&quot;&gt;Tef on Twitter&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=IoYUQlWiRgc&quot;&gt;&quot;The New View of Safety (video)&quot; by Todd
Conklin&lt;&#x2F;a&gt;: &quot;The next time
something goes wrong, switch you thinking from &#x27;who failed&#x27; to &#x27;what failed&#x27;.&quot;
Incredibly entertaining speaker talking at the United Steel Workers conference
on health safety and environment. It&#x27;s not directly about tech, but highly
applicable to tech.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;books.google.se&#x2F;books&#x2F;about&#x2F;The_Field_Guide_to_Understanding_Human_E.html?id=NTP5iLn4XHkC&amp;amp;redir_esc=y&quot;&gt;&quot;The Field Guide to Understanding Human
Error&quot; by Sidney Dekker&lt;&#x2F;a&gt;:
I&#x27;ve started this and plan to finish it over the holidays. But so far it&#x27;s
proben to be an incredibly useful resource reflecting on what failure is, and
how to think about it.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;how.complexsystems.fail&#x2F;&quot;&gt;&quot;How Complex Systems Fail&quot; by Richard
Cook&lt;&#x2F;a&gt;: A great overview of how to think
about failure, linking to relevant research backing up each point. Authored by
a medical doctor, but highly relevant to many fields including software
engineering.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;books.google.se&#x2F;books&#x2F;about&#x2F;Confessions_of_a_Recovering_Engineer.html?id=eKo_EAAAQBAJ&amp;amp;redir_esc=y&quot;&gt;&quot;Confessions of a Recovering Engineer: Transportation for a Strong
Town&quot;&lt;&#x2F;a&gt;:
An interesting dive into the world of transportation, how to think about
safety, and provides a perspective on the politics of institutionalized
engineering.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.usenix.org&#x2F;conference&#x2F;hotos-ix&#x2F;crash-only-software&quot;&gt;&quot;Crash-Only Software&quot; by Candea et
al.&lt;&#x2F;a&gt;: Another
classic computer science paper which I&#x27;d only ever heard about, but never
actually read. It provides interesting perspectives on failure modes in
computing, and how to deal with them.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;compilers&quot;&gt;Compilers&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;bytecodealliance.org&#x2F;articles&#x2F;cranelift-progress-2022&quot;&gt;&quot;Cranelift Progress in 2022&quot; by Chris
Fallin&lt;&#x2F;a&gt;: As
someone who likes compiler theory more than they enjoy working on compilers
directly, this post is a dream. It covers all the compiler improvements that
have happened on Cranelift over the past year. It&#x27;s super inspiring to see a
production-grade project have such a strong focus on correctness and
meaningfully better abstractions. Being able to follow this work in the open is
such a treat!&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.clear.rice.edu&#x2F;comp512&#x2F;Lectures&#x2F;Papers&#x2F;1971-allen-catalog.pdf?ref=dailydevbytes.com&quot;&gt;&quot;A catalogue of optimizing transformations&quot; by
Allen et al.&lt;&#x2F;a&gt;:
I&#x27;ve seen this paper referenced many times, but I didn&#x27;t actually read it
until this year. It&#x27;s pretty pragmatic in how it covers the main
optimizations a compiler can implement. Folks sometimes refer to this as: &quot;the
good ones&quot;, as just by implementing these you can get like 80% of the way there.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;miscellaneous-1&quot;&gt;Miscellaneous&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;dippedrusk.com&#x2F;posts&#x2F;2022-05-07-what-we-owe-each-other&#x2F;&quot;&gt;&quot;What we owe each other&quot; by Vagrant
Gautam&lt;&#x2F;a&gt;: A
really good post on justice, feelings, and accountability. Being a human can be
hard sometimes, and Vagrant does a fantastic job navigating this. Not an easy
read, but one that I found worthwhile.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;readme&#x2F;guides&#x2F;testable-requirements-feedback&quot;&gt;&quot;The Five Minute Feedback Fix&quot; by Hillel
Wayne&lt;&#x2F;a&gt;: shares
a practical formal verification technique which takes all of five minutes to
learn, and can be applied to virtually any language or project.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Bullshit_Jobs&quot;&gt;&quot;Bullshit Jobs&quot; by David
Graeber&lt;&#x2F;a&gt;: A reflection on the
nature of work, which felt relevant to me since, y&#x27;know, I&#x27;m a worker and all.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;datatracker.ietf.org&#x2F;doc&#x2F;rfc9110&quot;&gt;&quot;IETF RFC 9110: HTTP Semantics&quot; by Fielding et
al.&lt;&#x2F;a&gt;: The
IETF published a new series of HTTP specs this year, unifying the myriad of
previous documents into &quot;semantics&quot;, &quot;caching&quot;, and separate documents
for HTTP&#x2F;1.1, HTTP&#x2F;2, and HTTP&#x2F;3. The &quot;semantics&quot; document is fantastic
if you just want to learn how HTTP works, without going into the exact details
of the various backing wire protocols. I&#x27;m a big fan!&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I hope some of this was interesting. I&#x27;m off to finish reading some of the books
on this list. Happy holidays!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Rust 2023 (by Yosh)</title>
            <pubDate>Wed, 21 Dec 2022 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/rust-2023/</link>
            <guid>https://blog.yoshuawuyts.com/rust-2023/</guid>
            <description>&lt;p&gt;&lt;em&gt;Previous posts&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2022&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;: &lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@yoshuawuyts&#x2F;rust-mmxviii-but-like-from-my-perspective-6363f485ab2b&quot;&gt;2018&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;rust-2019&#x2F;&quot;&gt;2019&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;rust-2020&#x2F;&quot;&gt;2020&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;rust-2021&#x2F;&quot;&gt;2021&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2022&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;I didn&#x27;t write a &quot;Rust 2022&quot; post, sorry.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;The core team used to put out a yearly call for blog posts. My colleage Nick
published their &lt;a href=&quot;https:&#x2F;&#x2F;www.ncameron.org&#x2F;blog&#x2F;rust-in-2023&#x2F;&quot;&gt;&quot;Rust in 2023&quot;&lt;&#x2F;a&gt;
post last week, and encouraged others to do the same. I like the idea of taking
a moment to reflect on larger topics, and so well, why not write a post!&lt;&#x2F;p&gt;
&lt;p&gt;I want to do this a bit differently from the usual formula though. Rather than
writing something with the specific intent to build some sort of &quot;Rust 2023
roadmap&quot;, I want to instead take this as an opportunity to reflect on the state,
values, and priorities of the Rust project. More of a snapshot of my current
perspectives, than a concrete list of action items I think should be tackled.
Here goes!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;async&quot;&gt;Async&lt;&#x2F;h2&gt;
&lt;p&gt;Probably most of my work will continue to focus on async Rust. A majority of
programming jobs are either frontend or backend related &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#numbers&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, and async
is important to both. Anecdotally I know that async has been a major
driver for the adoption of Rust - and the more we can improve async Rust, likely
the better we&#x27;ll do in those fields.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;numbers&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;The 2022 stackoverflow survey notes 26% of people work on front-end,
and 43% of people do backend work. These numbers are non-exclusive, since folks
could be doing both
(&lt;a href=&quot;https:&#x2F;&#x2F;survey.stackoverflow.co&#x2F;2022&#x2F;#developer-roles-dev-type&quot;&gt;src&lt;&#x2F;a&gt;) - but I think
it&#x27;s fair to categorize this as a majority of jobs.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Work has been progressing a lot here. Diagnostics have become significantly
better. We now have &lt;code&gt;IntoFuture&lt;&#x2F;code&gt; stabilized. And both safe stack-pinning and
async fns in traits are on the horizon. And slightly further out is the work on
async iteration, async drop, async main, and keyword generics.&lt;&#x2F;p&gt;
&lt;p&gt;I should probably get around to writing the end-of-year update post for the
Async WG I promised I would write. But the tldr is that async Rust is important
to Rust&#x27;s future, we&#x27;ve made a lot of progress over the past year - and I think
we&#x27;re in a pretty good spot to keep making progress.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ambition&quot;&gt;Ambition&lt;&#x2F;h2&gt;
&lt;p&gt;It&#x27;s winter holidays, and I&#x27;m not going to ping people to clear quotes. But
someone I respect a lot once remarked: &lt;em&gt;&quot;Rust does best when we&#x27;re ambitious&quot;&lt;&#x2F;em&gt; -
and I agree strongly with this. I think the work we&#x27;re doing on Rust is far from
done. Rust is in a spot where people can be productive, but there are still so
many limitations. And when people run into this, I want us to do better than:
&quot;Well, that&#x27;s just the way things are&quot;. We can in fact have nice things!&lt;&#x2F;p&gt;
&lt;p&gt;As a general attitude, I want us to stay ambitious. To imagine a world in which
better things are in fact possible. And then doing the work to get there.  Rust
combines the desire for a radically better programming language with the
motivation to actually get things in people&#x27;s hands. And I think our work is
some ways only just getting started &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#lifetime&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;lifetime&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;It&#x27;s hard to say how long programming languages are expected to
last, but we&#x27;re seeing Rust adopted in some pretty high-stakes places which are
likely to stay around for &lt;em&gt;a very long time&lt;&#x2F;em&gt;. This means it&#x27;s possible Rust will
outlast us, meaning that in retrospect now might very well still be &quot;the early
days&quot; in terms of Rust adoption. We won&#x27;t know for sure until we&#x27;re there, but
imo this is not an unlikely outcome of our current trajectory.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fractal&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;I feel like everyone attributes this quote to someone else at this
point, but: the design space of a programming language is fractal! There are
infinite details to dig into, and there&#x27;s also a real art in deciding what to
prioritize.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;cohesion&quot;&gt;Cohesion&lt;&#x2F;h2&gt;
&lt;p&gt;&quot;What is Rust&quot; is one of those fun open-ended questions which doesn&#x27;t have a
right answer. After all: Rust is a programming language. Or maybe Rust is a
feeling in our hearts? I think Rust is the friends we make along the way.
Really, it&#x27;s us who get to decide what Rust means to us.&lt;&#x2F;p&gt;
&lt;p&gt;Pragmatically, I think Rust is &lt;em&gt;not just&lt;&#x2F;em&gt; a programming language. Cargo
is Rust. Rustup is Rust. Crates.io is Rust. All the tools,
guides, websites, people, and programs together make &quot;Rust&quot;. And I think that
with that come some interesting questions about governance, power, and cohesion
as well.&lt;&#x2F;p&gt;
&lt;p&gt;I won&#x27;t bore you with some long essay on the reflection of power dynamics within
open source ecosystems. But what I will say is that Rust has done remarkably
well in ensuring people using the language are presented with a relatively
cohesive experience! The compiler, formatter, versioning tool, guide, package
manager, and standard library are all owned and operated by the Rust project.
And I think this is a strength we should continue to build on.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m really happy that we&#x27;ve recently seen the addition of the &lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;2022&#x2F;06&#x2F;30&#x2F;Rust-1.62.0.html#cargo-add&quot;&gt;&lt;code&gt;cargo add&lt;&#x2F;code&gt;
command&lt;&#x2F;a&gt;, removing the need to rely on the external (yet trusted) &lt;code&gt;cargo-edit&lt;&#x2F;code&gt;
crate. And if I&#x27;m not mistaken work on
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;obi1kenobi&#x2F;cargo-semver-checks&quot;&gt;cargo-semver-checks&lt;&#x2F;a&gt; is
currently ongoing with the intent to integrate it into mainline cargo as well. &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#contrib&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;contrib&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;Somewhat proudly one of my own contributions along these lines in
the past year has been to bring the core functionality of the &lt;code&gt;num_cpus&lt;&#x2F;code&gt; crate
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;thread&#x2F;fn.available_parallelism.html&quot;&gt;into the
stdlib&lt;&#x2F;a&gt;. One
less crate to learn about!&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;I believe that one of the main strengths of Rust is that we&#x27;re creating
something together which looks and feels cohesive. I think it&#x27;s good to keep
adding features as long they end up feeling part of a whole. And I think this is
something that&#x27;s worth reflecting on, and identifying potential places where we
may be able to lean further into this.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;automation&quot;&gt;Automation&lt;&#x2F;h2&gt;
&lt;p&gt;I sometimes think about the 80&#x2F;20 rule: &quot;80% of work takes 20% of time; the
remaining 20% in 80% of time.&quot; I&#x27;m not sure if this has a proper name, but
there&#x27;s also what I like to call the 100% rule: &lt;em&gt;&quot;Once you&#x27;ve solved 100% of a
problem, you can stop thinking about it completely&quot;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Take for example memory safety in systems programming languages. Using fuzzers
and sanitizers you may be able to easily address 80% of bugs. But the remaining
20% of bugs will take some effort to find. And even when you do; code changes
over time, which means that you&#x27;ll be unlikely to ever afford to stop looking
for these types of bugs.&lt;&#x2F;p&gt;
&lt;p&gt;Compare that with the borrow checker, which guarantees there will &lt;em&gt;never&lt;&#x2F;em&gt; be any
memory safety bugs: meaning you can catagorically eliminate the concern
alltogether. The 80&#x2F;20 rule is often used to indicate that &quot;80% of effort is
good enough&quot;. But I think it&#x27;s important to realize that sometimes achieving 100%
of a solution can provide a value-add which far outweighs all incremental steps
that come before it.&lt;&#x2F;p&gt;
&lt;p&gt;I want us to keep looking for ways in which we can structurally eliminate issues
through automation, so we can stop thinking about them alltogether. Taking
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;obi1kenobi&#x2F;cargo-semver-checks&quot;&gt;cargo-semver-checks&lt;&#x2F;a&gt; as an
example again: rather than needing to learn and check for things like
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Covariance_and_contravariance_(computer_science)&quot;&gt;&quot;variance&quot; and &quot;contravariance&quot;&lt;&#x2F;a&gt;.
When publishing new versions of crates, we should just have a tool which checks
it for us - and patiently explains how we can fix the issues, even if we&#x27;re not
completely sure about what the underlying rules are.&lt;&#x2F;p&gt;
&lt;p&gt;I think it was Ralf Jung who once said something along the lines of: &lt;em&gt;&quot;The job of
an expert is to learn everything about a field there is to learn, and then
distill it so that others don&#x27;t have to.&quot;&lt;&#x2F;em&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#quote&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. And in my opinion
building tools is one of the best ways we have to propagate domain expertise.
I think this is something which we should keep leaning into &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#capabilities&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;quote&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;This was definitely a TWIR quote of the week at some point. I think
late 2020&#x2F;early 2021 ish? If someone remembers the link I&#x27;ll update this post!&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;capabilities&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;I believe programming language features such as the borrow
checker, or &lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;what-is-a-capability&#x2F;&quot;&gt;capabilities&lt;&#x2F;a&gt; fall
under this as well. Rather than memorizing and manually validating a set of
rules, we can&#x2F;should use automation (a compiler) to automate this reasoning for us.
Because for example even interpreted languages are not free from having to
reason about lifetimes and ownership; the only difference is that the language
doesn&#x27;t provide facilities to automate this reasoning. So people instead
have to rely on techniques such as defensive copying to prevent aliasing bugs from
occurring. (This could probably be a post on its own, so I&#x27;ll just stop here hah.)&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I can probably keep talking about Rust at length; that&#x27;s what this blog is for
after all. But I think these are some of the key points I wanted to hit. Before
closing out though, I probably should briefly cover my thoughts on governance:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I&#x27;m happy folks are working on governance. I trust them and their work.&lt;&#x2F;li&gt;
&lt;li&gt;I&#x27;m happy we&#x27;re seeing different variants of &quot;light weight RFCs&quot; popping up.
I believe both compiler (&lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rfcs&#x2F;2904-compiler-major-change-process.html&quot;&gt;MCP&lt;&#x2F;a&gt;) and libs (&lt;a href=&quot;https:&#x2F;&#x2F;std-dev-guide.rust-lang.org&#x2F;feature-lifecycle&#x2F;api-change-proposals.html&quot;&gt;ACP&lt;&#x2F;a&gt;) have these now, and I&#x27;m excited
to give some of these a shot.&lt;&#x2F;li&gt;
&lt;li&gt;Governance is fundamentally about relationships, and as long as the project
changes, so will governance. The work here will likely never be &quot;done&quot;, and
that&#x27;s probably just the nature of it.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;To close out: I think we&#x27;re doing great, and I&#x27;m excited for the direction
we&#x27;re headed. Happy 2023!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Async Iteration II: The Async Iterator Crate</title>
            <pubDate>Mon, 19 Dec 2022 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/async-iterator-crate/</link>
            <guid>https://blog.yoshuawuyts.com/async-iterator-crate/</guid>
            <description>&lt;hr &#x2F;&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-iteration&#x2F;&quot;&gt;Async Iteration I: Semantics&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-iterator-crate&#x2F;&quot;&gt;Async Iteration II: Async Iterator Crate&lt;&#x2F;a&gt; (this post)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-iterator-trait&quot;&gt;Async Iteration III: Async Iterator Trait&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Hey all, today was my first day back from PTO. While away, I was thinking what I
often think: I should write more on here. With Twitter effectively defunct, and
my Mastodon being set to ephemeral mode (posts auto-delete after 30 days), I
should start keeping a better record of what I&#x27;m up to somewhere more
&lt;em&gt;permanent&lt;&#x2F;em&gt;. And this blog seems as a good a place as any.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;async-iterator&quot;&gt;Async Iterator&lt;&#x2F;h2&gt;
&lt;p&gt;I wanted to share that I&#x27;ve published a crate:
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-iterator&#x2F;latest&#x2F;async_iterator&#x2F;&quot;&gt;&lt;code&gt;async-iterator&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Its
purpose was partly to test out the new &lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;inside-rust&#x2F;2022&#x2F;11&#x2F;17&#x2F;async-fn-in-trait-nightly.html&quot;&gt;&quot;async fn in traits&quot;&lt;&#x2F;a&gt; feature on
nightly. And partly to have a workable sketch of what we expect &quot;async iterator&quot;
to behave like.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_iterator::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;: impl Iterator&amp;lt;Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) -&amp;gt; Vec&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    iter.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span&gt;().await
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is not &lt;em&gt;final&lt;&#x2F;em&gt; shape of the trait though, since we&#x27;re working on &lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;inside-rust&#x2F;2022&#x2F;07&#x2F;27&#x2F;keyword-generics.html&quot;&gt;keyword
generics&lt;&#x2F;a&gt; and expect to retroactively add the &lt;code&gt;async Iterator&lt;&#x2F;code&gt; functionality to
the &lt;code&gt;Iterator&lt;&#x2F;code&gt; trait which then becomes generic over &quot;asyncness&quot;. But those
should just be the same semantics exposed through a different mechanism. Other
than that, the crate is pretty minimal, yet covers pretty much all the common
usage patterns:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The base async &lt;code&gt;Iterator&lt;&#x2F;code&gt; trait implemented through &lt;code&gt;async fn next&lt;&#x2F;code&gt; instead of &lt;code&gt;fn poll_next&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;The ability to &lt;code&gt;collect&lt;&#x2F;code&gt; into a &lt;code&gt;vec&lt;&#x2F;code&gt;, using  actual async &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; and &lt;code&gt;FromIterator&lt;&#x2F;code&gt; bounds&lt;&#x2F;li&gt;
&lt;li&gt;The ability to &lt;code&gt;async map&lt;&#x2F;code&gt; over values in the iterator&lt;&#x2F;li&gt;
&lt;li&gt;The ability to &lt;code&gt;extend&lt;&#x2F;code&gt; &lt;code&gt;vec&lt;&#x2F;code&gt; with an async iterator&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The only thing missing is &lt;code&gt;async fn filter&lt;&#x2F;code&gt;, which borrows items and so needs
some form of &quot;async closures&quot; to work. But all in all this means it works! -
&quot;async fn in traits&quot; is real on nightly, and actually does what we want it to
do! I think that&#x27;s really exciting! I don&#x27;t think the &lt;code&gt;async-iterator&lt;&#x2F;code&gt; crate
should be used in actual projects though. It&#x27;s an interface which only works on
nightly, and interfaces only really work when they&#x27;re uniformly adopted. And
between futures 0.3.0 and the stdlib I don&#x27;t think we should migrate to any
in-between interfaces in the interim. But I do think it will be really useful to
write experiments against!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;future-directions&quot;&gt;Future Directions&lt;&#x2F;h2&gt;
&lt;p&gt;I still have to check in with the &quot;async fns in traits&quot; team to see what they&#x27;re
up to (being gone for a month is a long time). But something I might consider
doing in the new year is do a rewrite of the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-h1&#x2F;latest&#x2F;async_h1&#x2F;&quot;&gt;async-h1 crate&lt;&#x2F;a&gt; based on
&quot;async fn in traits&quot;. The internals are basically a giant &lt;code&gt;poll&lt;&#x2F;code&gt;-based state
machine, and we&#x27;ve theorized for a while now that rewriting it in terms of
&lt;code&gt;async fn&lt;&#x2F;code&gt;s would significantly simplify its internals. It seems like this
should finally be possible, but I&#x27;ll have to check with folks first whether
doing this will actually be helpful now as well.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Keywords II: Const Syntax</title>
            <pubDate>Wed, 26 Oct 2022 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/const-syntax/</link>
            <guid>https://blog.yoshuawuyts.com/const-syntax/</guid>
            <description>&lt;p&gt;On the &lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;inside-rust&#x2F;2022&#x2F;07&#x2F;27&#x2F;keyword-generics.html&quot;&gt;Keyword Generics Initiative&lt;&#x2F;a&gt; we spend a lot of time talking about, well,
keyword generics! We&#x27;re working on designing a system which works with Rust&#x27;s
various &lt;em&gt;effects&lt;&#x2F;em&gt;, which are represented through keywords. And sometimes we
discover interesting interactions or meanings of keywords.&lt;&#x2F;p&gt;
&lt;p&gt;Previously I&#x27;ve written about the meaning of &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;unsafe-syntax&#x2F;&quot;&gt;&lt;code&gt;unsafe&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, showing how it actually
is a pair of keywords whose meaning depends on whether it&#x27;s in caller or
definition position. &lt;code&gt;const&lt;&#x2F;code&gt; shares some similarities to this, and in this post
we&#x27;ll be looking closer at the different uses of &lt;code&gt;const&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;always-const-execution&quot;&gt;always-const execution&lt;&#x2F;h2&gt;
&lt;p&gt;If you want to execute a function during compilation, you need to have a way to
make that happen. This is what we&#x27;ve been referring to as an &quot;always const&quot;
execution, where you have a context which will always be evaluated at
compile-time and never during runtime.&lt;&#x2F;p&gt;
&lt;p&gt;In Rust we can create an always-const context in a few different ways:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Defining a `const` value
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;HELLO&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str &lt;&#x2F;span&gt;&lt;span&gt;= {
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Defining a const value in an array expression
&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;; {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;}];
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Using `RFC 2920 experimental in-line const`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span&gt;{ &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; };
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; In const-generic parameters through `#![feature(`const_evaluatable_checked`)]`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; N: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;() -&amp;gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;; N + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;] { [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; N + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;} }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;These contexts also &lt;em&gt;disallow&lt;&#x2F;em&gt; the use of non-const values. Using them there
will quickly yield an error:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;; length];
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;   Compiling playground v0.0.1 (&#x2F;playground)
&lt;&#x2F;span&gt;&lt;span&gt;error[E0435]: attempt to use a non-constant value in a constant
&lt;&#x2F;span&gt;&lt;span&gt; --&amp;gt; src&#x2F;main.rs:5:11
&lt;&#x2F;span&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;span&gt;4 | fn foo(length: usize) {
&lt;&#x2F;span&gt;&lt;span&gt;  |        ------ this would need to be a `const`
&lt;&#x2F;span&gt;&lt;span&gt;5 |     [0u8; length];
&lt;&#x2F;span&gt;&lt;span&gt;  |           ^^^^^^
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;For more information about this error, try `rustc --explain E0435`.
&lt;&#x2F;span&gt;&lt;span&gt;error: could not compile `playground` due to previous error
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;never-const-execution&quot;&gt;never-const execution&lt;&#x2F;h2&gt;
&lt;p&gt;Code which cannot be evaluated during compilation is considered &quot;never-const&quot;.
These contexts are effectively &quot;runtime-only&quot;. Because &lt;code&gt;const&lt;&#x2F;code&gt; is opt-in in
today&#x27;s rust, it means that functions by default will not and cannot be
evaluated during compilation.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static str &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;HELLO&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;error[E0015]: cannot call non-const fn `hello` in constants
&lt;&#x2F;span&gt;&lt;span&gt; --&amp;gt; src&#x2F;lib.rs:5:23
&lt;&#x2F;span&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;span&gt;5 | const HELLO: &amp;amp;str = hello();
&lt;&#x2F;span&gt;&lt;span&gt;  |                     ^^^^^^^
&lt;&#x2F;span&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;span&gt;  = note: calls in constants are limited to constant functions, tuple structs and tuple variants
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;maybe-const-execution&quot;&gt;maybe-const execution&lt;&#x2F;h2&gt;
&lt;p&gt;The third type of &lt;code&gt;const&lt;&#x2F;code&gt; context is &quot;maybe-const&quot;. This is a context which can
be evaluated both during compilation and at runtime. The classic &lt;code&gt;const fn&lt;&#x2F;code&gt;
definition is considered a &quot;maybe-const&quot; context:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Can be evaluated both at runtime and during `const` execution.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;square&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;num&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    num * num
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Const evaluation
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;NUM&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64 &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;square&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Runtime evaluation
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;square&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As an aside: In practice both these functions will be evaluated during compilation
thanks to an optimization called &quot;const folding&quot;. But that&#x27;s just an
optimization; not all code can be const-folded, and the code wouldn&#x27;t compile if
it wasn&#x27;t valid at runtime. Whether or not a function is marked &lt;code&gt;const&lt;&#x2F;code&gt; has no
impact on whether or not the code will be const-folded. But I figured it&#x27;d at
least be worth mentioning the optimization as existing once in this post.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;const-traits&quot;&gt;const traits&lt;&#x2F;h2&gt;
&lt;p&gt;Something which we don&#x27;t yet have is the idea of &quot;const traits&quot;. Right now you
can think of them like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const trait &lt;&#x2F;span&gt;&lt;span&gt;Trait {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;func&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a &quot;const trait&quot; with a single &quot;const method&quot; which returns a type. Just
like &lt;code&gt;const fn&lt;&#x2F;code&gt;, this should be considered a &quot;maybe-const context&quot;: it should
both be able to be evaluated at runtime and during compilation. For example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; evaluates both at runtime and during compilation
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;~&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; Trait&amp;gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    T::func()
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;the-need-for-always-const-bounds&quot;&gt;the need for always-const bounds&lt;&#x2F;h2&gt;
&lt;p&gt;The current system of &lt;code&gt;const&lt;&#x2F;code&gt; syntax has some interesting limitations. Take for
example the following code:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Can be called at runtime with a `T` which doesn&amp;#39;t impl
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `const Trait`.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;~&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; Trait&amp;gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    [(); &amp;lt;T as Trait&amp;gt;::func()];
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;   ^ illegal
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What we&#x27;re seeing here is an &quot;always-const&quot; context nested in a &quot;maybe-const&quot;
context. A fun twist on the usual effect sandwich. In theory that should be
fine, but the issue here is that we&#x27;re using a variable which is &quot;maybe-const&quot;.
To get an understanding of why this is bad, here is roughly the same example,
but without the traits:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    [(); len];
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This yields the following error about wanting to have an &quot;always const&quot; value,
but what we got is a &quot;maybe const&quot; value:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;   Compiling playground v0.0.1 (&#x2F;playground)
&lt;&#x2F;span&gt;&lt;span&gt;error[E0435]: attempt to use a non-constant value in a constant
&lt;&#x2F;span&gt;&lt;span&gt; --&amp;gt; src&#x2F;lib.rs:2:9
&lt;&#x2F;span&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;span&gt;1 | const fn foo(len: usize) {
&lt;&#x2F;span&gt;&lt;span&gt;  |              --- this would need to be a `const`
&lt;&#x2F;span&gt;&lt;span&gt;2 |     [(); len];
&lt;&#x2F;span&gt;&lt;span&gt;  |          ^^^
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;For more information about this error, try `rustc --explain E0435`.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The earlier trait example this would yield a very similar error, but using more
steps. Thinking about solutions here, we practically have two ways to design
our way out of this:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Find a way to declare the maybe-const &lt;code&gt;foo&lt;&#x2F;code&gt; context as always-const.&lt;&#x2F;li&gt;
&lt;li&gt;Find a way to declare the maybe-const &lt;code&gt;T: ~const Trait&lt;&#x2F;code&gt; as always-const.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This is an unresolved problem, so we&#x27;re full on speculating here. But we could
imagine that if we support &lt;code&gt;~const Trait&lt;&#x2F;code&gt; meaning &quot;maybe-const&quot;, we could also
support &lt;code&gt;const Trait&lt;&#x2F;code&gt; to mean &quot;always const&quot;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; This now compiles because `T` is always guaranteed to be `const`.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; Trait&amp;gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    [(); &amp;lt;T as Trait&amp;gt;::func()];
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This gets us into a difficult spot though. This would create a difference
between the meaning of &lt;code&gt;const&lt;&#x2F;code&gt; when declared and when used in parameters.
Ideally we could, like, &lt;em&gt;not&lt;&#x2F;em&gt; have that. Because as we&#x27;ve seen in other places
having the same word mean different things in different contexts can be pretty
confusing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-need-to-specialize&quot;&gt;The need to specialize&lt;&#x2F;h2&gt;
&lt;p&gt;Another thing to mention here is the idea of &lt;em&gt;specialization&lt;&#x2F;em&gt;. In the compiler
we have &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;core&#x2F;intrinsics&#x2F;fn.const_eval_select.html&quot;&gt;&lt;code&gt;const_eval_select&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which allows you to specialize depending
on whether you&#x27;re executing at runtime or during compilation. This can be useful
to optimize implementations with, since more assumptions can be made about the
exact environment you&#x27;rer running on during runtime. During compilation Rust is
executed in an interpreter, which by design creates a uniform environment
regardless of what platform the compiler is actually running on.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;feature&lt;&#x2F;span&gt;&lt;span&gt;(const_eval_select)]
&lt;&#x2F;span&gt;&lt;span&gt;#![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;feature&lt;&#x2F;span&gt;&lt;span&gt;(core_intrinsics)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::intrinsics::const_eval_select;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; A function which returns a different result based on runtime or compiletime
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;inconsistent&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;runtime&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32 &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;compiletime&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32 &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;const_eval_select&lt;&#x2F;span&gt;&lt;span&gt;((), compiletime, runtime)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;CONST_X&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32 &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;inconsistent&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;inconsistent&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;assert!(x != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;CONST_X&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Something we&#x27;re talking about in the initiative group is: &quot;How can we enable
people to author different versions of the same resource which only
differentiate based on the effect?&quot; This would effectively fill the same role as
&lt;code&gt;const_eval_select&lt;&#x2F;code&gt;, but you could imagine it working for other effects such as
&lt;code&gt;async&lt;&#x2F;code&gt; as well. The syntax we&#x27;ve been playing around is some version of:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; maybe-async definition using an intrinsic to switch based on the context
&lt;&#x2F;span&gt;&lt;span&gt;async&amp;lt;A&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;async_eval_select&lt;&#x2F;span&gt;&lt;span&gt;(..) }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; the equivalent overload-based variant
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;}   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; always async
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;}         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; never async
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Something we haven&#x27;t really figured out is how we should define this for &lt;code&gt;const&lt;&#x2F;code&gt;
definitions. We&#x27;d want to declare two variants: one which is definitely not
const. And one which definitely is. And have these create a unified definition.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; maybe-const variant with the intrinsic
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;const_eval_select&lt;&#x2F;span&gt;&lt;span&gt;(..) }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; this wouldn&amp;#39;t work because we can&amp;#39;t define an &amp;quot;always const&amp;quot; context
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;{}   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; sometimes const
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;{}         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; never const
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;summary-what-is-const&quot;&gt;Summary: what is const?&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s recap everything we&#x27;ve seen about &lt;code&gt;const&lt;&#x2F;code&gt; so far. In today&#x27;s Rust the &lt;code&gt;const&lt;&#x2F;code&gt; effect
can roughly be thought of as having three different modes, split between
declaration and usage:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;declaration&lt;&#x2F;th&gt;&lt;th&gt;usage&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;keyword never applies&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn foo() {}&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn bar() { foo() }&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;keyword always applies&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;const FOO: () = {};&lt;&#x2F;code&gt;   &lt;em&gt;†&lt;&#x2F;em&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;keyword conditionally applies&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;const fn foo() {}&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;const fn bar() { foo() }&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;†: an &quot;always const&quot; context can only ever call &quot;maybe-const&quot; declarations
since there is no &quot;always-const&quot; declaration available in Rust today.&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The &lt;code&gt;const&lt;&#x2F;code&gt; keyword here means different things. &lt;code&gt;const FOO&lt;&#x2F;code&gt; is used to declare
an &quot;always-const&quot; context. But when you write &lt;code&gt;const fn foo&lt;&#x2F;code&gt; you&#x27;re in fact
declaring a &quot;sometimes-const&quot; context. &lt;strong&gt;This means &lt;code&gt;const&lt;&#x2F;code&gt; does not have a
consistent meaning in the language: depending on where it&#x27;s used, it may either
signal an &quot;always const&quot; context, or a &quot;maybe const&quot; context.&lt;&#x2F;strong&gt; And as we&#x27;ve
seen in the case of trait bounds, there is a meaningful observable distinction
between &quot;always const&quot; and &quot;maybe const&quot; contexts, bounds, and declarations.&lt;&#x2F;p&gt;
&lt;p&gt;This following table shows how &quot;const definitions&quot; interact with &quot;const
contexts&quot;. A &quot;never const&quot; context is runtime-only, an &quot;always const&quot; context is
compilation-only, and a &quot;sometimes const&quot; context can be evaluated both during
compilation and at runtime:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Can [def] be evaluated in [context]?&lt;&#x2F;th&gt;&lt;th&gt;never const context&lt;&#x2F;th&gt;&lt;th&gt;sometimes const context&lt;&#x2F;th&gt;&lt;th&gt;always const context&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;never const def&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;✅&lt;&#x2F;td&gt;&lt;td&gt;❌&lt;&#x2F;td&gt;&lt;td&gt;❌&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;sometimes const def&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;✅&lt;&#x2F;td&gt;&lt;td&gt;✅&lt;&#x2F;td&gt;&lt;td&gt;✅&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;always const def&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;❌&lt;&#x2F;td&gt;&lt;td&gt;❌&lt;&#x2F;td&gt;&lt;td&gt;✅&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;The way to think about &quot;const&quot; is as a subset of &quot;base&quot; Rust. We gain the
ability to evaluate code during compilation by removing capabilities from the
language. This means we don&#x27;t get the ability to access statics, or any host
functionality. Because &quot;const Rust&quot; is a subset of &quot;base Rust&quot;, you can also
think about it in an inverse and consider &quot;base Rust&quot; a superset of &quot;const
Rust&quot;. If we pull in &quot;async Rust&quot; as well, we can plot the following diagram:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;                   +---------------------------+                               
&lt;&#x2F;span&gt;&lt;span&gt;                   | +-----------------------+ |     Compute values:
&lt;&#x2F;span&gt;&lt;span&gt;                   | | +-------------------+ | |     - types
&lt;&#x2F;span&gt;&lt;span&gt;                   | | |                   | | |     - numbers
&lt;&#x2F;span&gt;&lt;span&gt;                   | | |    const Rust     |-------{ - functions               
&lt;&#x2F;span&gt;&lt;span&gt;                   | | |                   | | |     - control flow            
&lt;&#x2F;span&gt;&lt;span&gt; Host access:      | | +-------------------+ | |     - traits (planned)                 
&lt;&#x2F;span&gt;&lt;span&gt; - networking      | |                       | |     - containers (planned)
&lt;&#x2F;span&gt;&lt;span&gt; - filesystem  }-----|      &amp;quot;base&amp;quot; Rust      | |                               
&lt;&#x2F;span&gt;&lt;span&gt; - threads         | |                       | |                               
&lt;&#x2F;span&gt;&lt;span&gt; - system time     | +-----------------------+ |     
&lt;&#x2F;span&gt;&lt;span&gt; - statics         |                           |     Control over execution:      
&lt;&#x2F;span&gt;&lt;span&gt;                   |        async Rust         |---{ - ad-hoc concurrency      
&lt;&#x2F;span&gt;&lt;span&gt;                   |                           |     - ad-hoc cancellation&#x2F;pausing&#x2F;resumption
&lt;&#x2F;span&gt;&lt;span&gt;                   +---------------------------+     - higher-order control flow; ad-hoc timeouts, etc.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;back-to-the-drawing-board&quot;&gt;Back to the drawing board&lt;&#x2F;h2&gt;
&lt;p&gt;Okay, analysis time stops here. What I&#x27;ve said so far is mostly factual, and I
think we should be able to reference as mostly true for the foreseeable future.
From this point onward we put our imagination caps on and strap in to speculate
about &lt;em&gt;what could be&lt;&#x2F;em&gt;. If we could go back to the drawing board, how could we
change things?&lt;&#x2F;p&gt;
&lt;p&gt;Well, for one, we now know we not only want to have &quot;maybe const&quot; functions and
types. We also want &quot;maybe async&quot;, &quot;maybe throws&quot;; basically &quot;maybe &lt;em&gt;anything&lt;&#x2F;em&gt;&quot;
effects. The fact that &lt;code&gt;const fn&lt;&#x2F;code&gt; is &quot;maybe&quot; by default but &lt;code&gt;async&lt;&#x2F;code&gt; isn&#x27;t can be
a bit surprising. Here they are side-by-side:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;keyword &lt;code&gt;async&lt;&#x2F;code&gt;&lt;&#x2F;th&gt;&lt;th&gt;keyword &lt;code&gt;const&lt;&#x2F;code&gt;&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;keyword never applies&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn foo() {}&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn foo() {}&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;keyword always applies&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;async fn foo() {}&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;const FOO: () = {};&lt;&#x2F;code&gt;&lt;em&gt;†&lt;&#x2F;em&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;keyword conditionally applies&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;async&amp;lt;A&amp;gt; fn foo() {}&lt;&#x2F;code&gt; &lt;em&gt;‡&lt;&#x2F;em&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;const fn foo() {}&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;†: &quot;always-const&quot; functions don&#x27;t exist in Rust today, so an alternate method is shown here&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;‡ : placeholder syntax for functions where the keyword conditionally applies&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The difference is pretty striking right? We don&#x27;t have an &quot;always const&quot;
function. And what we mean by &quot;maybe const&quot; in one place means &quot;always async&quot; in
the other. When we look at &lt;em&gt;usage&lt;&#x2F;em&gt;, &lt;code&gt;const&lt;&#x2F;code&gt; and &lt;code&gt;async&lt;&#x2F;code&gt; look a lot more similar though:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Using `RFC 2920 experimental in-line const`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; value = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span&gt;{ &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; };
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; async block
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; value = async { &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; }.await;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;They&#x27;re not &lt;em&gt;quite&lt;&#x2F;em&gt; the same because they&#x27;re not the same feature. But the usage
here feels pretty good already. Now how could we bring the rest of &lt;code&gt;const&lt;&#x2F;code&gt; to
feel a bit more in line with the other keywords. Probably the boldest answer
would be to change the meaning of &lt;code&gt;const fn&lt;&#x2F;code&gt; to mean: &quot;always const&quot;. It could
then use a similar syntax to &quot;maybe async&quot; to declare &quot;maybe const&quot; contexts,
yielding us the following table:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;keyword &lt;code&gt;async&lt;&#x2F;code&gt;&lt;&#x2F;th&gt;&lt;th&gt;keyword &lt;code&gt;const&lt;&#x2F;code&gt;&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;keyword never applies&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn foo() {}&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn foo() {}&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;keyword always applies&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;async fn foo() {}&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;const fn foo() {}&lt;&#x2F;code&gt; &lt;em&gt;†&lt;&#x2F;em&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;keyword conditionally applies&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;async&amp;lt;A&amp;gt; fn foo() {}&lt;&#x2F;code&gt; &lt;em&gt;‡&lt;&#x2F;em&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;const&amp;lt;C&amp;gt; fn foo() {}&lt;&#x2F;code&gt; &lt;em&gt;‡&lt;&#x2F;em&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;† : &quot;always-const&quot; functions are new in this table, and use the existing &quot;maybe-const&quot; definition&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;‡ : placeholder syntax for functions where the keyword conditionally applies&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This would fix the main inconsistency between the effects, enabling them to be
used in a much more uniform manner. Looking at our earlier example, the original
formulation would have to become:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; declraring a &amp;quot;maybe const&amp;quot; context which takes &amp;quot;maybe const&amp;quot; params
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;C&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;C&amp;gt; Trait&amp;gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    [(); &amp;lt;T as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; Trait&amp;gt;::func()];
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;   ^ illegal; `T` must be &amp;quot;always const&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This, at least to me, feels like it more clearly describes the problem at hand.
&lt;code&gt;const fn&lt;&#x2F;code&gt; and &lt;code&gt;T: const&lt;&#x2F;code&gt; now use the same syntax to indicate they&#x27;re
conditional. And we&#x27;re trying to cast a &lt;code&gt;T&lt;&#x2F;code&gt; which is &quot;maybe const&quot; to be &quot;always
const&quot;. Diagnostics should make this fairly easy to point out.&lt;&#x2F;p&gt;
&lt;p&gt;This means the solutions to this issue could also be a lot clearer: we either
cast &lt;code&gt;T&lt;&#x2F;code&gt; to be &quot;always const&quot;, or mark the &lt;code&gt;const fn foo&lt;&#x2F;code&gt; to be an &quot;always const
context&quot;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; maybe-const fn foo, with an always-const trait T
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;C&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; Trait&amp;gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    [(); &amp;lt;T as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; Trait&amp;gt;::func()];
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; always-const fn foo, with an always-const trait T
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T: Trait&amp;gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    [(); &amp;lt;T as Trait&amp;gt;::func()];
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I&#x27;m less sure about having &lt;code&gt;const fn foo&lt;&#x2F;code&gt; imply that all generics are also
&lt;code&gt;const&lt;&#x2F;code&gt;, all casts are &lt;code&gt;const&lt;&#x2F;code&gt;, etc. Maybe they should be specified as &lt;code&gt;const&lt;&#x2F;code&gt;
as well? But on the other hand: they would have to be &lt;code&gt;const&lt;&#x2F;code&gt; for it to work, so
maybe it can be ommitted? Though that&#x27;s mostly a syntactical question, as it
wouldn&#x27;t affect the semantics.&lt;&#x2F;p&gt;
&lt;p&gt;Making the meaning of &lt;code&gt;const&lt;&#x2F;code&gt; unambiguous seems like it would make cases like
these a lot easier to work with. And it doesn&#x27;t just stop at bounds; if we
wanted to enable effect-based overloading, the example we saw earlier would Just
Work:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; maybe-const variant with the intrinsic
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;C&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;const_eval_select&lt;&#x2F;span&gt;&lt;span&gt;(..) }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; under the new rules this would be equivalent to a single &amp;quot;maybe const&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; declaration:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;{}   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; always const
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;{}         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; never const
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we were to introduce this change, I believe we could actually do it over an
edition bound. The main &quot;new&quot; feature is the ability to declare &quot;always-const&quot;
functions, traits, methods, etc. These couldn&#x27;t be declared in older editions;
but because changing an existing &quot;maybe-const&quot; definition to become
&quot;always-const&quot; would be considered a breaking change, it means that it wouldn&#x27;t
just break existing code simply by existing.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;const fn&lt;&#x2F;code&gt; code written on an older edition would be reinterpreted as
&quot;maybe-const&quot; in newer editions. And possibly we could also just add support for
trait bounds through &lt;code&gt;const&amp;lt;C&amp;gt;&lt;&#x2F;code&gt; on the old edition too, so on older editions
there would just be multiple ways to declare similar &quot;maybe const&quot; contexts:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! The different meanings of `const` between editions
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; old edition
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() {}                     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; maybe-const no traits
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;C&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;C&amp;gt; Foo&amp;gt;() {} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; maybe-const with traits
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; new edition
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() {}                     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; always const
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;C&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() {}                  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; maybe-const no traits
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;C&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;C&amp;gt; Foo&amp;gt;() {} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; maybe-const with traits
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Even if older editions can&amp;#39;t define always-const functions,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! they could still be available to older editions. The hardest part
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! is probably figuring out the diagnostics for the older edition to talk
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! about a concept which can be used, but not created.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; new edition: defines an always-const function
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;crate&lt;&#x2F;span&gt;&lt;span&gt; new {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() {}    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; always const declaration
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; old edition; uses an always-const function
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;crate&lt;&#x2F;span&gt;&lt;span&gt; old {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use super&lt;&#x2F;span&gt;&lt;span&gt;::new::foo;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; Foo: () = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;();  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; okay to call an always-const fn in an old edition
&lt;&#x2F;span&gt;&lt;span&gt;                            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; but no way to declare new ones
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As I&#x27;ve mentioned before: the exact syntax for conditional effects is still
undecided. But regardless of what we end up with, the idea is that we can create
something consistent between keywords.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve gone over what &lt;code&gt;const&lt;&#x2F;code&gt; is, how it relates to other keywords,
and gone deeper on the different uses and meanings of &lt;code&gt;const&lt;&#x2F;code&gt; in Rust today.
We&#x27;ve then taken a shot at trying to resolve these issues, with an outline of
how we could potentially normalize the meaning of the &lt;code&gt;const&lt;&#x2F;code&gt; keyword over an
edition bound.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;oli_obk&quot;&gt;Oli&lt;&#x2F;a&gt; for proof reading this post!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Inline Crates</title>
            <pubDate>Tue, 25 Oct 2022 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/inline-crates/</link>
            <guid>https://blog.yoshuawuyts.com/inline-crates/</guid>
            <description>&lt;p&gt;People sometimes jest that Rust is just ML dressed up to look like C++. And I
don&#x27;t think that&#x27;s entirely off: Rust has many of the key features present in ML
languages. We have the same kind of type system (&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Hindley%E2%80%93Milner_type_system&quot;&gt;Hindley-Milner&lt;&#x2F;a&gt;), we have
sum types, and we have a module system which isn&#x27;t directly tied to a module
hierarchy. I want to talk a bit more about Rust&#x27;s module system here.&lt;&#x2F;p&gt;
&lt;p&gt;In Rust we distinguish between &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;reference&#x2F;crates-and-source-files.html&quot;&gt;&quot;crates&quot;&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;reference&#x2F;items&#x2F;modules.html&quot;&gt;&quot;modules&quot;&lt;&#x2F;a&gt;. To people just
learning about Rust the distinction can be a bit confusing. But in practice it
makes sense to have both. In this post we&#x27;re going to take a look at Rust&#x27;s
module system, what the differences are, and how we could introduce some
features to bring crates and modules closer together.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Disclaimer: In this post I&#x27;m sharing some ideas on language design that heavily tie into
the current compiler architecture. I want to make it super clear that I&#x27;m not
necessarily advocating we make these changes, and I&#x27;m especially not trying to
say that this should be prioritized. I just wanted to have this written down so
it can be referenced later. Because I think there&#x27;s value in writing things
down even if they&#x27;re not fully formed, feasible, or quite the right time.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-are-crates&quot;&gt;What are crates?&lt;&#x2F;h2&gt;
&lt;p&gt;A crate is a unit of code with &lt;em&gt;strict&lt;&#x2F;em&gt; encapsulation rules: Crates are also
a unit which can individually be published to and pulled from crates.io. In the
compiler it represents a translation unit, and is the boundary of parallelization &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#llvm&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.
We&#x27;re only able to compile entire crates in parallel; not yet sub-components of
crates. And it also affects the boundaries of re-compilations.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;llvm&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;This is only about &lt;code&gt;rustc&lt;&#x2F;code&gt; specifically - the LLVM part of the
compilation may parallelize individual crates. You can read more on this in the
&lt;a href=&quot;https:&#x2F;&#x2F;rustc-dev-guide.rust-lang.org&#x2F;parallel-rustc.html#parallel-compilation&quot;&gt;rustc dev guide&lt;&#x2F;a&gt; and the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;rustc&#x2F;codegen-options&#x2F;index.html#codegen-units&quot;&gt;rustc book&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Crates themselves also have strict rules on disallowing cyclic dependencies
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#cycles&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, and of course the &lt;a href=&quot;http:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2015&#x2F;01&#x2F;14&#x2F;little-orphan-impls&quot;&gt;orphan rules&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#orphan-rules&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. A crate is always
tied to a file hierarchy on disk, and needs an accompanying &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt; file.
Matklad (of Rust-Analyzer fame) &lt;a href=&quot;https:&#x2F;&#x2F;matklad.github.io&#x2F;2021&#x2F;09&#x2F;04&#x2F;fast-rust-builds.html#compilation-model-crates&quot;&gt;goes into detail on their blog&lt;&#x2F;a&gt; how crates
affect compilation times, and how changing crate hierarchies can be used to
significantly improve throughput.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;cycles&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Given &lt;code&gt;a&lt;&#x2F;code&gt; and &lt;code&gt;b&lt;&#x2F;code&gt;. &lt;code&gt;a&lt;&#x2F;code&gt; can depend on &lt;code&gt;b&lt;&#x2F;code&gt;, or &lt;code&gt;b&lt;&#x2F;code&gt; can depend on &lt;code&gt;a&lt;&#x2F;code&gt;.
But they can&#x27;t both depend on each other, because that would cause a cycle in the dependency graph.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;orphan-rules&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Orphan rules come down to: if you want to implement a trait for
a type, you must either define the trait or the type in your crate. You&#x27;re not
allowed to implement a trait you haven&#x27;t defined for a type you haven&#x27;t defined.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Finally, some features such as &lt;a href=&quot;https:&#x2F;&#x2F;veykril.github.io&#x2F;tlborm&#x2F;proc-macros&#x2F;methodical.html&quot;&gt;procedural macros&lt;&#x2F;a&gt; can only be defined in crates
which have a specific configuration that disallows any other type of code to be
exported. Crates, more generally, also serve as a boundary of &lt;em&gt;configuration&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;backyard
&lt;&#x2F;span&gt;&lt;span&gt;├── Cargo.lock
&lt;&#x2F;span&gt;&lt;span&gt;├── Cargo.toml
&lt;&#x2F;span&gt;&lt;span&gt;└── src
&lt;&#x2F;span&gt;&lt;span&gt;    ├── garden
&lt;&#x2F;span&gt;&lt;span&gt;    │   └── vegetables.rs
&lt;&#x2F;span&gt;&lt;span&gt;    ├── garden.rs
&lt;&#x2F;span&gt;&lt;span&gt;    └── lib.rs
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;An example of a crate representation, copied from the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;book&#x2F;ch07-02-defining-modules-to-control-scope-and-privacy.html&quot;&gt;Rust book&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;For the purpose of this post we&#x27;ll not be talking on the Rust 2015-era concept
of &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;reference&#x2F;items&#x2F;extern-crates.html&quot;&gt;&lt;code&gt;extern crate&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-are-modules&quot;&gt;What are modules?&lt;&#x2F;h2&gt;
&lt;p&gt;A module is a unit of code with &lt;em&gt;loose&lt;&#x2F;em&gt; encapsulation rules: Cycles between
modules are allowed, and a module does not necessarily correspond to a file
hierarchy. Crates are a lightweight way of splitting code up into logical
components. Here&#x27;s an example of a valid &lt;code&gt;mod&lt;&#x2F;code&gt; relationship
(&lt;a href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=stable&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=82ceaad08832faea4dc55cbe049a87e4&quot;&gt;playground&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; example of cycles in modules
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub mod &lt;&#x2F;span&gt;&lt;span&gt;foo {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use super&lt;&#x2F;span&gt;&lt;span&gt;::bar::*;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;First;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub mod &lt;&#x2F;span&gt;&lt;span&gt;bar {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use super&lt;&#x2F;span&gt;&lt;span&gt;::foo::*;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Second;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But modules can also correspond to a file hierarchy. In the following example,
&lt;code&gt;backyard&lt;&#x2F;code&gt; is the crate, with &lt;code&gt;lib.rs&lt;&#x2F;code&gt; representing the entry point, and
internally contains &lt;code&gt;crate::garden&lt;&#x2F;code&gt;, and &lt;code&gt;crate::garden::vegetables&lt;&#x2F;code&gt; as
sub-modules:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;backyard
&lt;&#x2F;span&gt;&lt;span&gt;├── Cargo.lock
&lt;&#x2F;span&gt;&lt;span&gt;├── Cargo.toml
&lt;&#x2F;span&gt;&lt;span&gt;└── src
&lt;&#x2F;span&gt;&lt;span&gt;    ├── garden
&lt;&#x2F;span&gt;&lt;span&gt;    │   └── vegetables.rs
&lt;&#x2F;span&gt;&lt;span&gt;    ├── garden.rs
&lt;&#x2F;span&gt;&lt;span&gt;    └── lib.rs
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Modules also accept visibility modifiers such as &lt;code&gt;pub(crate)&lt;&#x2F;code&gt; or &lt;code&gt;pub(super)&lt;&#x2F;code&gt;. This
restricts the encapsulation rules somewhat by making the code accessible from
fewer sites. It also changes things like being able to access fields on structs.
But while it&#x27;s &lt;em&gt;stricter&lt;&#x2F;em&gt;, it still allows cycles between modules. Which is not
the same level of guarantees which crates provide.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;comparing-modules-and-crates&quot;&gt;comparing modules and crates&lt;&#x2F;h2&gt;
&lt;p&gt;To summarize what we&#x27;ve covered so far:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;name&lt;&#x2F;th&gt;&lt;th&gt;encapsulation&lt;&#x2F;th&gt;&lt;th&gt;file repr&lt;&#x2F;th&gt;&lt;th&gt;in-source repr&lt;&#x2F;th&gt;&lt;th&gt;cost to define and maintain&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;crate&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;strict&lt;&#x2F;td&gt;&lt;td&gt;✅&lt;&#x2F;td&gt;&lt;td&gt;❌&lt;&#x2F;td&gt;&lt;td&gt;high&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;mod&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;loose&lt;&#x2F;td&gt;&lt;td&gt;✅&lt;&#x2F;td&gt;&lt;td&gt;✅&lt;&#x2F;td&gt;&lt;td&gt;low&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Crates and modules are both incredibly useful concepts, with benefits and
tradeoffs. But today it&#x27;s significantly harder to define new crates, than it is
to define new modules. Features like &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;cargo&#x2F;reference&#x2F;specifying-dependencies.html#inheriting-a-dependency-from-a-workspace&quot;&gt;&quot;workspace inheritence&quot;&lt;&#x2F;a&gt; lower the barrier
somewhat, but there&#x27;s still a pretty large difference between how easy they are
to introduce to your project.&lt;&#x2F;p&gt;
&lt;p&gt;Adding a new module is basically just adding a &lt;code&gt;mod {}&lt;&#x2F;code&gt; and copying over the
right imports - something which Rust-Analyzer can even do for you. But adding a
new crate is far more involved: it requires creating a new module hierarchy,
adding the right dependencies, adding the right imports to the workspace, and
then linking the right imports back to the crates you want to use. This could be
automated as well, but that only makes authoring crates easier - it doesn&#x27;t help
with readability.&lt;&#x2F;p&gt;
&lt;p&gt;And that&#x27;s not even taking into account &lt;em&gt;releasing&lt;&#x2F;em&gt; crates. When you add a new
&lt;code&gt;mod&lt;&#x2F;code&gt; to a crate it doesn&#x27;t affect the ability to publish new crates. But when
you create a new crate, you now have a new dependency. Which must be accurately
versioned &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#versioning&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; and published before the main crate can be released. The
fact that &quot;strict encapsulation semantics&quot; are necessarily tied to an on-disk
hierarchy is not ideal.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;versioning&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;&quot;workspace inheritence&quot; can also help with versioning here.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;in-line-modules&quot;&gt;in-line modules&lt;&#x2F;h2&gt;
&lt;p&gt;You can probably see where this is going. In my opinion Rust would benefit from
detaching crates from the module hierarchy, and allowing them to also be defined
in a manner similar to modules. A single &quot;crate&quot; should be able to contain many
sub-crates, all of which enforce the same strict encapsulation rules as their
on-disk counterparts. The only difference being in how they&#x27;re declared. Much
like &lt;code&gt;workspace.inherit&lt;&#x2F;code&gt;, sub-crates would inherit the dependencies and version
number of their parent crate. And unlike on-disk crates, they wouldn&#x27;t be
individually publishable to crates.io, but instead just be sent along with their
parent crates.&lt;&#x2F;p&gt;
&lt;p&gt;To give an example of what this would look like; I&#x27;m thinking we adopt a very
similar syntax to modules:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mod &lt;&#x2F;span&gt;&lt;span&gt;foo {}   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; define an in-line module
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;crate&lt;&#x2F;span&gt;&lt;span&gt; foo {} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; define an in-line crate
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mod &lt;&#x2F;span&gt;&lt;span&gt;bin;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; import a module from a file
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;crate&lt;&#x2F;span&gt;&lt;span&gt; bin;   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; import a crate from a file
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;example&quot;&gt;Example&lt;&#x2F;h2&gt;
&lt;p&gt;Being able to distinguish at the source-level between &quot;public&quot; and &quot;private&quot;
crates is something which would be useful for larger projects in particular. An
example of such a project is probably Rust-Analyzer, which I happen to be
familiar with.&lt;&#x2F;p&gt;
&lt;p&gt;You can see an overview of all crates in the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust-analyzer&#x2F;blob&#x2F;82ff740501e1da239a6c9ff94dddf7ae1ca9aeb6&#x2F;docs&#x2F;dev&#x2F;architecture.md#code-map&quot;&gt;code map&lt;&#x2F;a&gt; section of the
&lt;a href=&quot;https:&#x2F;&#x2F;matklad.github.io&#x2F;2021&#x2F;02&#x2F;06&#x2F;ARCHITECTURE.md.html&quot;&gt;architecture.md&lt;&#x2F;a&gt; file. Rust-Analyzer clearly distinguishes between &lt;a href=&quot;https:&#x2F;&#x2F;www.tedinski.com&#x2F;2018&#x2F;02&#x2F;06&#x2F;system-boundaries.html&quot;&gt;&quot;API
boundary&quot;&lt;&#x2F;a&gt; crates, and all other crates. For example something like the &lt;code&gt;ide&lt;&#x2F;code&gt;
crate is a &quot;boundary&quot;, but internally uses other crates such as &lt;code&gt;ide-db&lt;&#x2F;code&gt;, and
&lt;code&gt;ide-assists&lt;&#x2F;code&gt; which are not boundaries:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;crates&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;hir-def&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;hir-expand&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;hir-ty&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;hir&#x2F;             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# boundary
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ide-assists&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ide-completion&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ide-db&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ide-diagnostics&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ide-ssr&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ide&#x2F;             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# boundary
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I&#x27;ve contributed to Rust-Analyzer in the past, but I&#x27;m not on the RA team - so I
can&#x27;t speak with any authority about the project. But it&#x27;s not unreasonable that
a project similar to Rust-Analyzer could benefit from only surfacing the API
boundary crates in the top-level crate hierarchy - without needing to give up
the strict encapsulation rules Rust crates provide.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;crates&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;hir&#x2F;             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# boundary
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;def&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;expand&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ty&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ide&#x2F;             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;# boundary
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;assists&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;completion&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;db&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;diagnostics&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ssr&#x2F;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There may be projects who prefer to use a flat module hierarchy even if in-line
crates become available. But when starting it seems easier to be able to quickly
define a new crate, and only later move it to its own hierarchy. The point of
the &lt;code&gt;crate&lt;&#x2F;code&gt; keyword is to enable strict encapsulation without immediately having
to resort to separate on-disk representations. Which should make it possible to
let the structure found during prototyping hold all the way. As opposed of the
current status quo where prototypes can be started using &lt;code&gt;mod&lt;&#x2F;code&gt; statements, but
eventually you&#x27;ll want to refactor into separate crates.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;implementation&quot;&gt;Implementation&lt;&#x2F;h2&gt;
&lt;p&gt;I suspect implementing inline crates might not be an easy task. If I&#x27;m not
mistaken &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#wesleywesley&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, right now parallelism of compilation is driven by
&lt;code&gt;cargo&lt;&#x2F;code&gt; spawning a bunch of instances of &lt;code&gt;rustc&lt;&#x2F;code&gt; which compile individual
crates. If crates are represented as anything other than something you can point
&lt;code&gt;rustc(1)&lt;&#x2F;code&gt; to compile, it might need some rethinking of the architecture.&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t think that&#x27;s an argument &lt;em&gt;against&lt;&#x2F;em&gt; inline crates though. But rather a
reflection that the architecture of how we&#x27;ve organized the various rust
compiler projects is reflected in the features provided it provides &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#conway&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. And things
features such as inline exist right at the seems of where the two projects meet.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;wesleywesley&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;Wesley checked this and said my understanding of this is indeed
correct. I really wasn&#x27;t sure about this in earlier drafts, but I&#x27;m thankful I
was able to confirm ^^.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;conway&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;See: &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Conway%27s_law&quot;&gt;Conway&#x27;s law&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;future-directions&quot;&gt;Future Directions&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;pub-crate&quot;&gt;pub crate&lt;&#x2F;h3&gt;
&lt;p&gt;Alright, time to speculate a little. Conversations around &quot;crates.io namespaces&quot;
pop up pretty regularly. The basic idea is that sometimes crates are
correlated, and being able to group them together under a single namespace would
be nice.&lt;&#x2F;p&gt;
&lt;p&gt;Take for example the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;windows&quot;&gt;&lt;code&gt;windows&lt;&#x2F;code&gt; crate&lt;&#x2F;a&gt;. It&#x27;s probably the single biggest crate
on crates.io &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#size&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Internally it&#x27;s built up of lots of crates which are all
versioned in lock-step, and hidden behind feature flags.  Take for example
&lt;code&gt;win32&lt;&#x2F;code&gt;&#x27;s HTTP service API. To use it with the &lt;code&gt;windows&lt;&#x2F;code&gt; crate you&#x27;d need to
define it in your toml like so:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;size&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;I believe it exposes something like 30.000 unique types and traits.
Like an order of magnitude more than e.g.
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;web-sys&#x2F;latest&#x2F;web_sys&#x2F;&quot;&gt;&lt;code&gt;web-sys&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; does, which covers &lt;em&gt;the
entire web platform&lt;&#x2F;em&gt;. &lt;code&gt;windows&lt;&#x2F;code&gt; is a pretty good example for a &quot;big&quot; crate that
needs to be broken up into sub-components for the compiler to even attempt to
build it in reasonable time.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;toml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-toml &quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span&gt;[dependencies]
&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;windows&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; = { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;version &lt;&#x2F;span&gt;&lt;span&gt;= &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;0.41.0&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;features &lt;&#x2F;span&gt;&lt;span&gt;= [&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Win32_Networking_HttpServer&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;] }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Instead, if the &lt;code&gt;windows&lt;&#x2F;code&gt; crate could be used as a namespace, we could imagine
that instead of exclusively exposing APIs using feature flags, we may want to
expose it as crates namespaced under &lt;code&gt;windows&lt;&#x2F;code&gt;. For example, we could imagine
something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-toml &quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span&gt;[dependencies]
&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;windows&#x2F;win32_networking_httpserver&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;0.41.0&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are some big &quot;ifs&quot; involved here: we&#x27;re assuming this can be neatly split
out into a single crate. But let&#x27;s assume we can. How would we split it out?
Today that would mean creating a new hierarchy on disk, and putting the right
code there. And then in turn resolving the dependency hierarchy ahead of time to
correctly version and publish the dependencies in the right order.&lt;&#x2F;p&gt;
&lt;p&gt;What if we could have an &lt;code&gt;1:N&lt;&#x2F;code&gt; mapping to published crates from within crates?
What if the definition inside the windows crate could look like this and it
would be enough to both provide the feature from inside the &lt;code&gt;windows&lt;&#x2F;code&gt; crate, and
be publicly accessible as a sub-crate?:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cfg&lt;&#x2F;span&gt;&lt;span&gt;(feature = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Win32_Networking_HttpServer&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub crate&lt;&#x2F;span&gt;&lt;span&gt; win32_networking_httpserver { ... }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I&#x27;d imagine the dependencies and versions would all be shared from the
&lt;code&gt;Cargo.toml&lt;&#x2F;code&gt; definition. And dependencies between inline crates would be
extrapolated and extracted into the manifest. I don&#x27;t think this should
&lt;em&gt;replace&lt;&#x2F;em&gt; workspaces in any way. Workspaces are a great feature, and give a
great deal of control. But it seems like it could be a way to lower the overall
burden of authoring new packages.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;wasi-components&quot;&gt;WASI components&lt;&#x2F;h3&gt;
&lt;p&gt;And to continue the speculation: I&#x27;ve been wondering for a few months now
whether we could provide an &lt;code&gt;1:N&lt;&#x2F;code&gt; mapping of Rust programs to &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;component-model&quot;&gt;WASI
components&lt;&#x2F;a&gt;. In WebAssembly
components serve as a boundary of strict encapsulation, not unlike but als not
exactly along the lines of crates in Rust.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m fairly optimistic that WASI will present a best-in-class target to compile
Rust to for networked services. And if we&#x27;re able to provide fine-grained and
easy-to-use mappings from Rust to WASI components, it might give Rust an edge
over other languages. I suspect being able to lean into the strict encapsulation
semantics of Rust crates may have meaningful benefits wrt compile targets that
we&#x27;re currently unable to leverage to its full potential &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#more&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;more&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;&#x2F;sup&gt;
&lt;p&gt;I&#x27;m trying not to go full in on WASI encapsulation rules, and mapping
Rust programs to WASI. But I think there&#x27;s a lot there, and being able to define
in-line crates may end up being a component in a full WASI story.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;That&#x27;s about it I think. I would love to see more equivalence between &quot;crates&quot;
and &quot;modules&quot; in Rust. Even if we one day see a loosening of the orphan rules,
or we see Rust move to fine-grained paralellism - having in-line crates will
still be useful, as they&#x27;re easier to create and modify than their on-disk
counterparts. Even if it&#x27;s just to prototype and experiment before wanting to
commit to a final design.&lt;&#x2F;p&gt;
&lt;p&gt;To come entirely clean: I don&#x27;t see this work panning out anytime soon. It would
require an effective rearchitecture of the compiler, and by itself this feature
wouldn&#x27;t carry its weight to justify doing that. But perhaps if enough reasons
build up, eventually we&#x27;ll look to make the changes which would &lt;em&gt;also&lt;&#x2F;em&gt; enable
this feature. Either way, I figured it&#x27;d be worth spelling this out.&lt;&#x2F;p&gt;
&lt;p&gt;I think we could ask some very interesting questions about what other benefits
such a rearchitecture of the compiler could look like as well. Could compilation
become more efficient? Could it become easier to optimize builds? What would we
lose? What other features could be enabled? Even if we know we don&#x27;t have the
time for any of this now, I do think it&#x27;s 1: fun to think about, and 2: perhaps
something useful will come out of it.&lt;&#x2F;p&gt;
&lt;p&gt;I also want to at least state once that I don&#x27;t believe this should be in place
of any workspace improvements. But I see working &lt;em&gt;in addition to&lt;&#x2F;em&gt; workspace
improvements. I view both approaches as improvements to status quo, and I think they would end up complimenting each other rather well!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;wesleywiser&quot;&gt;Wesley Wiser&lt;&#x2F;a&gt; for proof reading!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Why Async Rust</title>
            <pubDate>Mon, 26 Sep 2022 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/why-async-rust/</link>
            <guid>https://blog.yoshuawuyts.com/why-async-rust/</guid>
            <description>&lt;p&gt;A lot of system design is about thinking of the nature of the domains we
encounter. And only later, once we understand them, encoding this understanding
in a way that machines can verify it.&lt;&#x2F;p&gt;
&lt;p&gt;I often find async Rust to be misunderstood. Conversations around &quot;why
async&quot; often focus on performance &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#async-book&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; - a topic which is highly dependent on
workloads, and results with people wholly talking past each other. While
performance is not a &lt;em&gt;bad&lt;&#x2F;em&gt; reason to choose async Rust, we often we only notice
performance when we experience a lack of it. So I want to instead on which
&lt;em&gt;features&lt;&#x2F;em&gt; async Rust provides which aren&#x27;t present in non-async Rust. Though
we&#x27;ll talk a bit about performance too at the end of this post.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;async-book&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;async-book&#x2F;01_getting_started&#x2F;02_why_async.html&quot;&gt;introduction to the Rust async book&lt;&#x2F;a&gt; summarizes the
benefits of async Rust as follows: &quot;In summary, asynchronous programming allows
highly performant implementations that are suitable for low-level languages like
Rust, while providing most of the ergonomic benefits of threads and coroutines.&quot;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;language-hierarchy&quot;&gt;Language Hierarchy&lt;&#x2F;h2&gt;
&lt;p&gt;It&#x27;s not uncommon to hear Rust and other languages described as &quot;N languages in
a trenchcoat&quot;. In Rust we have Rust&#x27;s control flow constructs, we have the
decl-macro meta language, we we have the trait system (which is
&lt;a href=&quot;https:&#x2F;&#x2F;sdleffler.github.io&#x2F;RustTypeSystemTuringComplete&#x2F;&quot;&gt;turing-complete&lt;&#x2F;a&gt;), we have the cfg annotation language - and the list keeps
going. But if we consider Rust as it is provided out of the box to us, as &quot;base
Rust&quot; then there are some obvious modifiers to it:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;unsafe&lt;&#x2F;code&gt; Rust: to use raw pointers and FFI&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;const&lt;&#x2F;code&gt; Rust: to compute values at compile-time&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;async&lt;&#x2F;code&gt; Rust: to enable non-blocking computation&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;All of these &quot;modifier keyword&quot; to the Rust language provide new capabilities
which aren&#x27;t present in &quot;base Rust&quot;. But they may sometimes also take
capabilities away. The way I&#x27;ve started thinking and talking about language
features is in terms of &quot;subset of the language&quot; or &quot;superset of the language&quot;.
With that classification we can look at the modifier keywords again and make the
following categorization:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;unsafe&lt;&#x2F;code&gt; Rust: superset&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;const&lt;&#x2F;code&gt; Rust: subset&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;async&lt;&#x2F;code&gt; Rust: superset&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;code&gt;unsafe&lt;&#x2F;code&gt; Rust only &lt;em&gt;adds&lt;&#x2F;em&gt; the ability to use raw pointers. &lt;code&gt;async&lt;&#x2F;code&gt; only adds the
ability to &lt;code&gt;.await&lt;&#x2F;code&gt; values. But &lt;code&gt;const&lt;&#x2F;code&gt; &lt;em&gt;adds&lt;&#x2F;em&gt; the ability to compute values
during compilation, but &lt;em&gt;removes&lt;&#x2F;em&gt; the ability to use statics and access things
like the network or filesystem.&lt;&#x2F;p&gt;
&lt;p&gt;If language features only &lt;em&gt;add&lt;&#x2F;em&gt; to base Rust then they&#x27;re considered supersets.
But if the features they add require they also restrict other features, then
they&#x27;re considered subsets. In the case of &lt;code&gt;const&lt;&#x2F;code&gt;, all &lt;code&gt;const&lt;&#x2F;code&gt; functions can be
executed at runtime. But not all code which can be executed at runtime can be
marked as &lt;code&gt;const&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The design of language features as sub&#x2F;supersets of &quot;base&quot; Rust is essential: it
ensures that the language keeps feeling &lt;em&gt;cohesive&lt;&#x2F;em&gt;. And more so than size or
scope, &lt;a href=&quot;https:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2022&#x2F;09&#x2F;22&#x2F;rust-2024-the-year-of-everywhere&#x2F;#making-rust-feel-simpler-by-making-it-more-uniform&quot;&gt;uniformity is what leads to the feeling of simplicity&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;async-under-the-hood&quot;&gt;async under the hood&lt;&#x2F;h2&gt;
&lt;p&gt;At its core &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; in Rust provides a standardized way to return types
with a method on them that returns another type. Instead of returning a type
directly, &lt;code&gt;async&lt;&#x2F;code&gt; functions return an intermediate type first. &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#monad&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;monad&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Sure; &quot;monad&quot; 🙃&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; This function returns a string
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read_to_string&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: Path) -&amp;gt; String { .. }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; This function returns a type which eventually returns a string
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read_to_string&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: Path) -&amp;gt; String { .. }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Instead of using `async fn` we can also write it like this.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; `impl Future` here is a type-erased struct
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read_to_string&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: Path) -&amp;gt; impl Future&amp;lt;Output = String&amp;gt; { .. }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A future is just a type with a method on it (&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;future&#x2F;trait.Future.html#tymethod.poll&quot;&gt;&lt;code&gt;fn poll&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;). If we call the method
at the right times and in the right way, then eventually it&#x27;ll give us the
equivalent of &lt;code&gt;Option&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; where &lt;code&gt;T&lt;&#x2F;code&gt; is the value that we wanted.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;A future is just a type with a method we can call&quot; has a few implications.
First of all, just like we can choose to call the method, we can also choose to
not call the method. If we don&#x27;t call the method at all then the future won&#x27;t
execute any work &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#exception1&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Or we can choose to call it, and then &lt;em&gt;stop&lt;&#x2F;em&gt;
calling it for a while. Maybe we just call the method again later. We can even
choose to drop the struct at any point, and then there&#x27;s no more method to call
and no more value to be obtained.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;exception1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Yes, that&#x27;s only the case for &lt;code&gt;async fn &#x2F; async {}&lt;&#x2F;code&gt;-futures. If
you &lt;code&gt;-&amp;gt; impl Future&lt;&#x2F;code&gt; you can do work &lt;em&gt;before&lt;&#x2F;em&gt; constructing the future and
returning it. But that&#x27;s not considered a great pattern, and it&#x27;s pretty rare
in practice.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;When we talk about &quot;representing a computation in a type&quot;, we&#x27;re actually
talking about compiling down the &lt;code&gt;async fn&lt;&#x2F;code&gt; and all of its &lt;code&gt;.await&lt;&#x2F;code&gt; points into
a state machine which knows how to suspend and resume from the various &lt;code&gt;.await&lt;&#x2F;code&gt;
points. These state machines are just structs with some fields in them, and
and have an auto-generated &lt;code&gt;Future::poll&lt;&#x2F;code&gt; implementation which knows how to
correctly transition between the various states. To learn more about how
these state machines work, I recommend watching &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;ZHP9sUqB3Qs&quot;&gt;&quot;life of an async fn&quot; by
tmandry&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;.await&lt;&#x2F;code&gt; syntax provides a way to ensure that none of the underlying &lt;code&gt;poll&lt;&#x2F;code&gt;
details surface in the user-syntax. Most usage of &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; looks just like
non-async Rust, but with &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; annotations sprinkled on top.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rust-s-async-features&quot;&gt;Rust&#x27;s Async Features&lt;&#x2F;h2&gt;
&lt;p&gt;The core feature &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; provides in Rust is &lt;em&gt;control over execution&lt;&#x2F;em&gt;.
Instead of the contract being:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;&amp;gt; &amp;quot;function call&amp;quot; -&amp;gt; &amp;quot;output&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We instead get access to an intermediate step:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;&amp;gt; &amp;quot;function call&amp;quot; -&amp;gt; &amp;quot;computation&amp;quot; -&amp;gt; &amp;quot;output&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The computation isn&#x27;t just something which is hidden away from us anymore. With
&lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; we are empowered to manipulate the computation itself. This leads
to several key capabilities:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The ability to suspend&#x2F;cancel&#x2F;pause&#x2F;resume computation (ad-hoc cancellation)&lt;&#x2F;li&gt;
&lt;li&gt;The ability to execute computations concurrently (ad-hoc concurrency)&lt;&#x2F;li&gt;
&lt;li&gt;The ability to combine control over execution, cancellation, and concurrency&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;ad-hoc-cancellation&quot;&gt;ad-hoc cancellation&lt;&#x2F;h3&gt;
&lt;p&gt;The ability to suspend&#x2F;cancel&#x2F;pause&#x2F;resume any computation is incredibly useful. Out of the
three being able to cancel execution is likely the most useful one. In
both sync and async code it&#x27;s both desireable to halt execution before it
completes. But what&#x27;s unique to async Rust is that &lt;em&gt;any&lt;&#x2F;em&gt; computation can be
halted in a uniform way. &lt;strong&gt;Every future can be cancelled, and all futures need to
account for that &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#cancellation-safety&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;cancellation-safety&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;Yes I&#x27;m fully aware of the concept of &quot;cancellation-safety&quot;,
and I have a post coming up discussing it in more detail. The tldr:
&quot;cancellation-safety&quot; as a concept is under-specified, but importantly:
&quot;cancellation-safety&quot; is only relevevant when using &lt;code&gt;select! {}&lt;&#x2F;code&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;futures-concurrency-3&#x2F;&quot;&gt;which is
something which should not be
used&lt;&#x2F;a&gt;. Correctly
handling cancellation is something that manually authored futures still need to
do though, and that can be tricky to do without &quot;async Drop&quot;. But that&#x27;s
different from &quot;cancellation-safety&quot; or the idea that futures don&#x27;t need to have
to account for being cancelled at all.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;ad-hoc-concurrency&quot;&gt;ad-hoc concurrency&lt;&#x2F;h3&gt;
&lt;p&gt;The ability to execute computations concurrently is another hallmark capability
of async Rust. Any number of &lt;code&gt;async fn&lt;&#x2F;code&gt;s can be run concurrently &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#deadlocks&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;,
and &lt;code&gt;.await&lt;&#x2F;code&gt;ed together. In non-async Rust concurrency is typically tied
to parallelism: many computations can be scheduled concurrently by using
&lt;code&gt;thread::spawn&lt;&#x2F;code&gt; and splitting it up that way. But async Rust separates concurrency
from parallelism, providing more control &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#libs&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. In non-async Rust concurrency
and parallelism are interlinked, which among other things has performance
implications. We&#x27;ll talk more about the differences later in this post.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;deadlocks&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;Bar any runtime faults such as deadlocks, which can occur if two
computations are run concurrently but share a resource.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;libs&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;Not all libraries make use of the separation between &quot;concurrency&quot; and
&quot;parallelism&quot; though. We&#x27;re still very much figuring out what async Rust even
is, but many of the libraries in common use today don&#x27;t necessarily surface this
insight. I know many of my own older libraries sure don&#x27;t.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;combining-cancellation-and-concurrency&quot;&gt;combining cancellation and concurrency&lt;&#x2F;h3&gt;
&lt;p&gt;Now finally: when happens when you combine &lt;em&gt;cancellation&lt;&#x2F;em&gt; and &lt;em&gt;concurrency&lt;&#x2F;em&gt;? It
allows us to do some interesting things! In my blog post &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-cancellation-2&#x2F;&quot;&gt;&quot;Async Time III:
Cancellation and Signals&quot;&lt;&#x2F;a&gt; I
go in-depth on some of the things you can do with this. But the canonical
example here is: timeouts. A timeout is a concurrent execution of some future
and a timer future, mapped to a &lt;code&gt;Result&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;If the future completes before the timer, we cancel the timer and return &lt;code&gt;Ok&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;If the timer completes before the future, we cancel the future and return &lt;code&gt;Err&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That&#x27;s cancellation + concurrency combined to provide a new third type of
operation. To get a sense for why being able to time-out any computation is a
useful property, I highly recommend reading &lt;a href=&quot;https:&#x2F;&#x2F;www.usenix.org&#x2F;conference&#x2F;hotos-ix&#x2F;crash-only-software&quot;&gt;Crash-Only Software by Candea and
Fox&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#ty&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. But it doesn&#x27;t just stop at timeouts: if we combine any of the
suspend&#x2F;cancel&#x2F;pause&#x2F;resume capabilities with concurrency, we unlock a myriad of
new possible operations.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;ty&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;Shout out to Eric Holk for introducing me to this paper!&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;These are the features async Rust enables. In non-async Rust concurrency,
cancellation, and suspensions often require calling out to the underlying operating
system - and it&#x27;s not always supported. For example: Rust doesn&#x27;t have a
built-in way to cancel threads. The way to do it is usually to pass a channel to
a thread, and periodically check it to see if some &quot;cancel&quot; message has been
passed.&lt;&#x2F;p&gt;
&lt;p&gt;In contrast in async Rust &lt;em&gt;any&lt;&#x2F;em&gt; computation can be paused, cancelled, or run
concurrently. That doesn&#x27;t mean that all computations should be run
concurrently, or everything should have a timeout on it. But those decisions can
be made on the basis of what we&#x27;re implementing, rather than being limited by
external factors such as system call availability.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;performance-workloads&quot;&gt;Performance: workloads&lt;&#x2F;h2&gt;
&lt;p&gt;When something is stated to perform better than something else, it&#x27;s always
worth asking: &lt;em&gt;&quot;under which circumstances?&quot;&lt;&#x2F;em&gt; Performance is  always dependent on
the workload. In graphics cards benchmarks you&#x27;ll often see differences between
video cards based on which games are run. In CPU benchmarks it matters a lot
whether a workload is primarily single-threaded or multi-threaded. And when we
talk about software features &quot;performance&quot; is not a binary either, but highly
dependent on the workload. When talking about parallel processing we can
distinguish between two general categories of workloads:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;throughput-oriented workloads&lt;&#x2F;li&gt;
&lt;li&gt;latency-oriented workloads&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Thoughput-oriented workloads usually care about processing the maximum number of
things in the shortest amount of time. While latency-oriented workloads care about
processing each thing as quickly as possible. Sounds confusing? Let&#x27;s make it
more clear.&lt;&#x2F;p&gt;
&lt;p&gt;An example of software designed with throughput in mind is
&lt;a href=&quot;https:&#x2F;&#x2F;cloud.google.com&#x2F;learn&#x2F;what-is-hadoop&quot;&gt;hadoop&lt;&#x2F;a&gt;. It&#x27;s built for
&quot;offline&quot; batch processing of workloads; where the most important design goal is
to minimize the total CPU time spent to process data. When data is put into the
system it may often take minutes or even hours to be processed. And that&#x27;s fine.
We don&#x27;t care &lt;em&gt;when&lt;&#x2F;em&gt; we get the results (within reason of course), we primarily
care about using as few resources as possible to get the results.&lt;&#x2F;p&gt;
&lt;p&gt;Compare that to a public-facing HTTP server. Networking is typically
&lt;em&gt;latency-oriented&lt;&#x2F;em&gt;. We often care less about how many requests we can handle,
than &lt;em&gt;how quickly we can respond to them&lt;&#x2F;em&gt;. When a request comes in we don&#x27;t want
to take minutes or hours to generate a response. We want request-response
roundtrips to be measured in at most milliseconds. And things like
p99 &lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;12808989&quot;&gt;tail-latencies&lt;&#x2F;a&gt; are often used as key performance indicators.&lt;&#x2F;p&gt;
&lt;p&gt;Async Rust is generally considered to be more latency-oriented than
throughput-oriented. Runtimes such as &lt;code&gt;async-std&lt;&#x2F;code&gt; and &lt;code&gt;tokio&lt;&#x2F;code&gt; primarily care
about keeping overall latency low, and preventing sudden latency-spikes.&lt;&#x2F;p&gt;
&lt;p&gt;Understanding what type of workload is being discussed is often the first step
in discussing performance. A key benefit of async Rust is that most of the systems
which use it have been tuned heavily to provide good performance for
latency-oriented workloads - of which networking is an example. If you want
to handle more throughput-oriented workloads, non-async crates like
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rayon&#x2F;latest&#x2F;rayon&#x2F;&quot;&gt;&lt;code&gt;rayon&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; are often a better fit.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;performance-optimizations&quot;&gt;Performance: optimizations&lt;&#x2F;h2&gt;
&lt;p&gt;Async Rust separates &lt;em&gt;concurrency&lt;&#x2F;em&gt; and &lt;em&gt;parallelism&lt;&#x2F;em&gt; from each other. Sometimes
the two are confused with each other, but they are in fact different:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;parallelism is a resource, concurrency is a way of scheduling computation&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It&#x27;s best to think of &quot;parallelism&quot; as a maximum. For example, if your computer has two cores, the maximum amount of parallelism you have may be two &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#exceptions-par&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.
But parallelism is different from concurrency: computation can be interleaved on a single
core, so while we&#x27;re waiting on the network to perform work, we can run some other
computations until we have a response. Even on single-threaded machines,
computation can be interleaved and concurrent. And vice-versa: just because we&#x27;ve
scheduled things in parallel doesn&#x27;t mean computation is interleaved. No matter
how many cores we&#x27;re running on, if threads are taking turns by waiting on a
single, shared lock, then the logical execution may in fact still happen sequentially.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;exceptions-par&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;&#x2F;sup&gt;
&lt;p&gt;This is a simplified example; for a longer explainer see the
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;thread&#x2F;fn.available_parallelism.html&quot;&gt;std::thread::available_parallelism&lt;&#x2F;a&gt;
docs.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Let&#x27;s take a look at an example of a concurrent workload in async and non-async
Rust. In non-async Rust it&#x27;s most common to use threads to achieve concurrent
execution &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#exception2&quot;&gt;9&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. But since threads are also the abstraction to achieve
&lt;em&gt;parallel&lt;&#x2F;em&gt; execution, it means that in non-async Rust &lt;em&gt;concurrency&lt;&#x2F;em&gt; and
&lt;em&gt;parallelism&lt;&#x2F;em&gt; are often tightly interlinked.&lt;&#x2F;p&gt;
&lt;p&gt;In async Rust, we can separate concurrency from parallelism. If a workload is
&lt;em&gt;concurrent&lt;&#x2F;em&gt;, it doesn&#x27;t imply it is also &lt;em&gt;parallelizable&lt;&#x2F;em&gt; as well. This
provides finer control over execution, which is the key strength of async Rust.
Let&#x27;s compare concurrency in non-async and async Rust:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;exception2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;9&lt;&#x2F;sup&gt;
&lt;p&gt;Unless you start manually writing
&lt;a href=&quot;https:&#x2F;&#x2F;linux.die.net&#x2F;man&#x2F;7&#x2F;epoll&quot;&gt;&lt;code&gt;epoll(7)&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; loops, and hand-roll state
machines. At some point you may start thinking about creating abstractions to
make these state machines compose better with each other, at which point you&#x27;ve
basically arrived at futures again. Natively, in order to achieve: &quot;I want to
make this code run concurrently&quot;, threads are the easiest, most convenient
abstraction available in non-async Rust.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; thread-based concurrent computation
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x = thread::spawn(|| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; y = thread::spawn(|| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(x, y) = (x.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(), y.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;()); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; wait for both threads to return
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; async-based concurrent computation
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x = async { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; y = async { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(x, y) = (x, y).await;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; resolve both futures concurrently
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This may seem like a pretty silly example: computation is synchronous and so
both do the same thing, but the non-async variant has the overhead of needing to spawn actual
threads. And it doesn&#x27;t stop there: because the second example doesn&#x27;t need
threads, the compiler&#x27;s inliner can kick in, and may be able to optimize it to
the following &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#godbolt&quot;&gt;10&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; compiler-optimized async-based concurrent computation
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(x, y) = (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In contrast, the best optimization the compiler can likely perform for the
thread-based variant is:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; thread-based concurrent computation
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x = thread::spawn(|| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; y = thread::spawn(|| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(x, y) = (x.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(), y.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;()); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; wait for both threads to return
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;godbolt&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;10&lt;&#x2F;sup&gt;
&lt;p&gt;Note that this exact example doesn&#x27;t yet work in the optimizer, but
that I don&#x27;t believe there is any strong reason why it couldn&#x27;t either. It&#x27;s all
local reasoning, with no cross-thread synchronization needed. The closest
example I have for optimizations of this kind is this example of a hand-rolled
version of &lt;a href=&quot;https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;3df34MGYv&quot;&gt;&lt;code&gt;block_on&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which compiles down to
absolutely nothing. This cheats a little bit by removing not using an
atomic-based &lt;code&gt;Arc&lt;&#x2F;code&gt;, so I&#x27;m not sure how realistic it is. But it&#x27;s def something
to aspire to, and I&#x27;m optimistic that as async Rust sees more usage, we&#x27;ll see
more async-specific optimizations as well.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Separating concurrency from parallelism allows for more optimizations of
computations. &lt;code&gt;async&lt;&#x2F;code&gt; in Rust is basically a fancy way of authoring a state
machine, and nested &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; calls allow types to be compiled down into
singular state machines. Sometimes &lt;a href=&quot;https:&#x2F;&#x2F;without.boats&#x2F;blog&#x2F;futures-and-segmented-stacks&#x2F;&quot;&gt;we may want to separate the state
machines&lt;&#x2F;a&gt; though, but
that&#x27;s the sort of control which async Rust provides us with, which is harder to
achieve using non-async Rust.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ecosystem&quot;&gt;Ecosystem&lt;&#x2F;h2&gt;
&lt;p&gt;Before we close out, we should point out one last
reason people may choose async Rust: the size of the ecosystem. Without &lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;inside-rust&#x2F;2022&#x2F;07&#x2F;27&#x2F;keyword-generics.html&quot;&gt;keyword
generics&lt;&#x2F;a&gt; it can be a lot of work for library authors to publish and maintain
libraries which work both in async and non-async Rust. Often it&#x27;s easiest to
just publish either an async or non-async library, and not account for the other
use case. A lot of the network-related libraries on crates.io use async Rust
though, which means that libraries building on top of this will also use async
Rust. And in turn people looking to build websites without rewriting everything
from scratch will often have a larger ecosystem to choose from when using async
Rust.&lt;&#x2F;p&gt;
&lt;p&gt;Network effects are real and need to be acknowledged in this context. Not everyone wanting to
build a website will be thinking in terms of language features, but may instead
just be looking at the options they have in terms of ecosystem. And that&#x27;s a
perfectly valid reason to use async Rust for too.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Sometimes conversations pop up about async Rust with suggestions such as:
&quot;What if we disallowed cancellation in its entirety?&quot; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#rationale&quot;&gt;11&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; Seeing this
always confuses me, because it seems it carries a fundamental misunderstanding
of what async Rust provides and why it should be used. If the focus is solely
on performance, features such as cancellation or &lt;code&gt;.await&lt;&#x2F;code&gt; annotations may seem
like a plain nuisance.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;rationale&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;11&lt;&#x2F;sup&gt;
&lt;p&gt;The goal of this is often to have linear-futures, or &quot;futures
which are guaranteed to complete&quot;. The way by which cancellation would be
disallowed is only the &quot;stop polling&quot; kind. You should still be able to pass
channels around to cancel things, at least that&#x27;s the theory. Though I believe
there may also be implications for concurrency, which would make this really
tough.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;But if the focus is more on the features async Rust enables, things like
cancellation and timeouts quickly rise from nuisance to key reasons to adopt
async Rust. Async Rust grants us the ability to control execution in a way which
just isn&#x27;t possible in non-async Rust. And frankly, isn&#x27;t even possible in many
other programming languages featuring &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; either. The fact that an
&lt;code&gt;async fn&lt;&#x2F;code&gt; compiles down to a lazy state machine instead of an eager managed
task is a crucial distinction. And it means that we can author concurrency
primitives entirely in library code, rather than needing to build it into the
compiler or runtime.&lt;&#x2F;p&gt;
&lt;p&gt;In async Rust the features it enables build on each other. Here&#x27;s a brief
summary of how they relate:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;            Yosh&amp;#39;s Hierarchy
&lt;&#x2F;span&gt;&lt;span&gt;        of Rust Async Capabilities
&lt;&#x2F;span&gt;&lt;span&gt;    ┌───────────────────────────────┐
&lt;&#x2F;span&gt;&lt;span&gt;3.  │   Timeouts, Timers, Signals   │  …which can then be composed into…
&lt;&#x2F;span&gt;&lt;span&gt;    ├───────────────┬───────────────┤
&lt;&#x2F;span&gt;&lt;span&gt;2.  │ Cancellation  │  Concurrency  │  …which in turn enable…
&lt;&#x2F;span&gt;&lt;span&gt;    ├───────────────┴───────────────┤
&lt;&#x2F;span&gt;&lt;span&gt;1.  │    Control over Execution     │  The core futures enable…
&lt;&#x2F;span&gt;&lt;span&gt;    └───────────────────────────────┘
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We also briefly covered the performance aspect of async Rust. Generally speaking
it &lt;em&gt;can&lt;&#x2F;em&gt; be more performant than non-async Rust when you&#x27;re doing async IO. But
that will mostly be the case when the underlying system APIs are geared for
that, which usually includes networking APIs, and more recently has also started
including disk IO.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;_lrlna&quot;&gt;Iryna Shestak&lt;&#x2F;a&gt; for proof reading this post and providing helpful feedback along the way.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Futures Concurrency IV: Join Ergonomics</title>
            <pubDate>Mon, 19 Sep 2022 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/futures-concurrency-4/</link>
            <guid>https://blog.yoshuawuyts.com/futures-concurrency-4/</guid>
            <description>&lt;p&gt;On Thursday this week Rust 1.64 will be released, and in it it will include a
stabilized version of &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;future&#x2F;trait.IntoFuture.html&quot;&gt;&lt;code&gt;IntoFuture&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Much like &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; is used in the
desugaring of &lt;code&gt;for..in&lt;&#x2F;code&gt; loops, &lt;code&gt;IntoFuture&lt;&#x2F;code&gt; will be used in the desugaring of
&lt;code&gt;.await&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In this post I want to show some of the ergonomics improvements &lt;code&gt;IntoFuture&lt;&#x2F;code&gt; might
enable, inspired by Swift&#x27;s recent improvements in &lt;code&gt;async&#x2F;await&lt;&#x2F;code&gt; ergonomics.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;async-let-in-swift&quot;&gt;async let in swift&lt;&#x2F;h2&gt;
&lt;p&gt;Swift has recently added support for &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;apple&#x2F;swift-evolution&#x2F;blob&#x2F;main&#x2F;proposals&#x2F;0317-async-let.md&quot;&gt;&lt;code&gt;async let&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#async-let&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; in the language.
This provides lightweight syntax to create Swift tasks, which before this
proposal always had to be constructed explicitly within a &lt;em&gt;task group&lt;&#x2F;em&gt;. In the
evolution proposal they show an example like this:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;async-let&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;J. McCall, J. Groff, D. Gregor, and K. Malawski, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;apple&#x2F;swift-evolution&#x2F;blob&#x2F;main&#x2F;proposals&#x2F;0317-async-let.md&quot;&gt;“SE-0317: async let bindings,” Mar. 25, 2021&lt;&#x2F;a&gt;. (accessed Apr. 07, 2022).&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;swift&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-swift &quot;&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;func &lt;&#x2F;span&gt;&lt;span&gt;makeDinner() async -&amp;gt; Meal {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create a task group to scope the lifetime of our three child tasks
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return try&lt;&#x2F;span&gt;&lt;span&gt; await withThrowingTaskGroup(of: CookingTask.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) { group &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; spawn three cooking tasks and execute them in parallel:
&lt;&#x2F;span&gt;&lt;span&gt;    group.async {
&lt;&#x2F;span&gt;&lt;span&gt;        CookingTask.veggies(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;try&lt;&#x2F;span&gt;&lt;span&gt; await chopVegetables())
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    group.async {
&lt;&#x2F;span&gt;&lt;span&gt;        CookingTask.meat(await marinateMeat())
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    group.async {
&lt;&#x2F;span&gt;&lt;span&gt;        CookingTask.oven(await preheatOven(temperature: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;350&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ... a whole lot more code after this
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s quite a bit of code. And &lt;code&gt;async let&lt;&#x2F;code&gt; exists to simplify that. Instead of
explicitly creating the task group and manually creating tasks within it, using
&lt;code&gt;async let&lt;&#x2F;code&gt; the right scope is inferred for us &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#note&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, and instead the
concurrency is expressed at the &lt;code&gt;await&lt;&#x2F;code&gt; point later on:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;note&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;I may be wrong on the details here. It&#x27;s been a sec since I last read
the Swift post, and I only glanced over the details today for this post. It
shouldn&#x27;t matter too much tho for the purpose of this post since we&#x27;re mostly
focusing on the end-user experience.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;swift&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-swift &quot;&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;func &lt;&#x2F;span&gt;&lt;span&gt;makeDinner() async throws -&amp;gt; Meal {
&lt;&#x2F;span&gt;&lt;span&gt;  async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; veggies = chopVegetables()
&lt;&#x2F;span&gt;&lt;span&gt;  async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; meat = marinateMeat()
&lt;&#x2F;span&gt;&lt;span&gt;  async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; oven = preheatOven(temperature: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;350&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; dish = Dish(ingredients: await [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;try&lt;&#x2F;span&gt;&lt;span&gt; veggies, meat]) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; notice the concurrent await here
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return try&lt;&#x2F;span&gt;&lt;span&gt; await oven.cook(dish, duration: .hours(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This feels very elegant in comparison, and definitely feels like a step up for
Swift. I think the flow of this is so good in fact, that we may want to adopt
something similar in Rust.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;join-in-rust&quot;&gt;Join in Rust&lt;&#x2F;h2&gt;
&lt;p&gt;In Rust we already have a notion of a &quot;concurrent await&quot; through the &lt;code&gt;join&lt;&#x2F;code&gt;
operation. If you do async Rust you&#x27;ve likely seen it before in macro-form as
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;latest&#x2F;futures&#x2F;macro.join.html&quot;&gt;&lt;code&gt;join!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; or the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;latest&#x2F;futures&#x2F;future&#x2F;fn.join_all.html&quot;&gt;&lt;code&gt;join_all&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; free-function:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; example of the `join!` macro:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(join!(a, b, c).await, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; example of the `join_all` free-function:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; futs = vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;ready&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;)];
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join_all&lt;&#x2F;span&gt;&lt;span&gt;(futs).await, [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In my &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;futures-concurrency-2&quot;&gt;Futures Concurrency II&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#conc-2&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; post and &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-concurrency&#x2F;latest&#x2F;futures_concurrency&quot;&gt;library&lt;&#x2F;a&gt; I show that instead of using a
combination of macros and free functions we can instead use traits to extend
container types with the necessary concurrency operations. This results in a
smoother experience overall, since arrays, tuples, and vectors all operate in
the same way:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;conc-2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Y. Wuyts, &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;futures-concurrency-2&quot;&gt;“Futures Concurrency II,” Sep. 02, 2021&lt;&#x2F;a&gt;. (accessed Apr. 11, 2022).&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; alternative to the `join!` macro:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!((a, b, c).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;().await, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; alternative to the `join_all` free-function:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(vec![a, b, c].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;().await, vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This works fine, but it&#x27;s not quite as good as what swift has using &lt;code&gt;async let&lt;&#x2F;code&gt;.
Let&#x27;s take a look at how we can improve that.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;join-ergonomics&quot;&gt;Join Ergonomics&lt;&#x2F;h2&gt;
&lt;p&gt;Awaiting a single future is done by calling &lt;code&gt;.await&lt;&#x2F;code&gt;, but awaiting multiple
futures requires calling an intermediate method. To get &lt;code&gt;join&lt;&#x2F;code&gt; semantics you have
to call the &lt;code&gt;join&lt;&#x2F;code&gt; method, rather than just being able to await a tuple of futures.&lt;&#x2F;p&gt;
&lt;p&gt;This is where &lt;code&gt;IntoFuture&lt;&#x2F;code&gt; can help: we can use it to implement a conversion
to a future directly on tuples, arrays, and vectors - and make it so if they
contain futures you can just call &lt;code&gt;.await&lt;&#x2F;code&gt; on them directly to await all futures
concurrently. With that in place the above example could be rewritten like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!((a, b, c).await, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;));    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; no more `.join()` needed
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(vec![a, b, c].await, vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]);  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; no more `.join()` needed
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While being substantially different under the hood, the surface-level experience of
this is actually quite similar to Swift&#x27;s &lt;code&gt;async let&lt;&#x2F;code&gt;. We just don&#x27;t operate by
default on tasks owned by a runtime, but futures which are lazy and compile down
to in-line state machines. But this could be made to trivially work with
multi-threaded Rust tasks too, if we follow the spawn approach laid out by
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tasky&#x2F;latest&#x2F;tasky&#x2F;&quot;&gt;tasky&lt;&#x2F;a&gt; (&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;postfix-spawn&#x2F;&quot;&gt;blog post&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#tasky-post&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;) &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#tasky-note&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;tasky-post&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;Y. Wuyts, &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;postfix-spawn&#x2F;&quot;&gt;“Postfix Spawn,” Mar. 04, 2022&lt;&#x2F;a&gt;. (accessed Sep. 18, 2022).&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;tasky-note&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;I should explain this model in more detail at some point. The
core of it is that we treat parallelism as a resource, and concurrency as a way
of scheduling work. We mark futures which are &quot;parallelizable&quot; as such, and then
pass them to the existing concurrency operators just like any other future. That
creates a unified approach to concurrency for both parallel and non-parallel
workloads.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!((a, b, c).await, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;));    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; parallelized `await`
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(vec![a, b, c].await, vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]);  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; parallelized `await`
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This, to me, feels like a pretty good outcome for concurrent and parallel
awaiting of fixed-sized sets of futures. Awaiting sets of futures which change
over time is a different problem, and will likely require something akin to
Swift&#x27;s &lt;code&gt;TaskSet&lt;&#x2F;code&gt; to function. But that&#x27;s not most concurrent workloads, and I
think we can take a page out of Swift&#x27;s book on this.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;other-operations&quot;&gt;Other Operations&lt;&#x2F;h2&gt;
&lt;p&gt;In &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;futures-concurrency-3&#x2F;&quot;&gt;a past post&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fut-conc-3&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; I&#x27;ve shown the following table of
concurrency operations for futures:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fut-conc-3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;Y. Wuyts, &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;futures-concurrency-3&#x2F;&quot;&gt;“Futures Concurrency III: select,” Feb. 09, 2022&lt;&#x2F;a&gt;. (accessed Apr. 06, 2022).&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Wait for all outputs&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Wait for first output&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Continue on error&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::join&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::try_race&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Return early on error&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::try_join&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::race&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;code&gt;join&lt;&#x2F;code&gt; is only one of 4 different concurrency operations. When you have
different futures you may in fact want to do different things with it. But not
all operations are equal: when we have two or more futures, it&#x27;s usually because
we&#x27;re interested in observing all of their output. &lt;code&gt;join&lt;&#x2F;code&gt; gives us exactly that.
We&#x27;ll get to &lt;code&gt;try_&lt;&#x2F;code&gt; variants in the next section, but for now take for the
following example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = a.await;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = b.await;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This first awaits &lt;code&gt;a&lt;&#x2F;code&gt;, and then it awaits &lt;code&gt;b&lt;&#x2F;code&gt;. Because the two are unrelated,
it&#x27;s often more efficient to await them &lt;em&gt;concurrently&lt;&#x2F;em&gt; rather than
&lt;em&gt;sequentially&lt;&#x2F;em&gt;. With (async) &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; we&#x27;re handed tools required to operate
over values sequentially. But with &lt;code&gt;IntoFuture&lt;&#x2F;code&gt; we&#x27;re handed tools to operate
over values &lt;em&gt;concurrently&lt;&#x2F;em&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#iter-note&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;iter-note&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;code&gt;IntoIterator&lt;&#x2F;code&gt; is not implemented for tuples, only for arrays and
vectors. To make this example work we&#x27;ll just use arrays. Perhaps we can one day
use tuples too like this, but that may require having variadic tuples and maybe
even structurally-typed enums for it to work.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `IntoIterator` enables sequential operation
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; num in [a, b] { .. }   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; sequential iteration
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `IntoFuture` enables concurrent operation
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;[a, b] = [a, b].await; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; concurrent await
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The design of &lt;code&gt;IntoFuture&lt;&#x2F;code&gt; intentionally mirrors the design of &lt;code&gt;IntoIterator&lt;&#x2F;code&gt;.
For any type &lt;code&gt;T&lt;&#x2F;code&gt; we can only have a single &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; implementation. This
leaves us with a few options:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;don&#x27;t implement &lt;code&gt;IntoFuture&lt;&#x2F;code&gt; for containers&lt;&#x2F;li&gt;
&lt;li&gt;implement &lt;code&gt;join&lt;&#x2F;code&gt; semantics for containers&lt;&#x2F;li&gt;
&lt;li&gt;implement &lt;code&gt;race&lt;&#x2F;code&gt; semantics for containers&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This post is argues that &lt;code&gt;2.&lt;&#x2F;code&gt; is a chance to provide better ergonomics than
&lt;code&gt;1.&lt;&#x2F;code&gt;. But what about &lt;code&gt;3.&lt;&#x2F;code&gt;? Could we meaningfully have &lt;code&gt;race&lt;&#x2F;code&gt; semantics as the
default? &lt;code&gt;race&lt;&#x2F;code&gt; takes N futures and yields one result. This would look like
this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span&gt;= [a, b].await; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `race`-semantics
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I&#x27;ve said it before, but this seems like a minority use case. We&#x27;ll almost always
want &lt;code&gt;a AND b&lt;&#x2F;code&gt;. Not &lt;code&gt;a XOR b&lt;&#x2F;code&gt;. At least: we may still want to drop the values
later on, but it&#x27;s usually not decided based on which completed first. &lt;code&gt;join&lt;&#x2F;code&gt;
also feels like it extends the existing behavior of &lt;code&gt;await&lt;&#x2F;code&gt; for individual
futures to sets of futures. &lt;code&gt;race&lt;&#x2F;code&gt; exposes different semantics than a plain
&lt;code&gt;.await&lt;&#x2F;code&gt; does, and so if awaiting tuples of futures was different, the
resulting experience would feel inconsistent.&lt;&#x2F;p&gt;
&lt;p&gt;It seems good to have &lt;code&gt;join&lt;&#x2F;code&gt; be the default semantics exposed through
&lt;code&gt;IntoFuture&lt;&#x2F;code&gt;, but then have operations such as &lt;code&gt;race&lt;&#x2F;code&gt; and &lt;code&gt;merge&lt;&#x2F;code&gt; be explicit
forms of concurrency you can instead opt into by calling the right method.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fallibility&quot;&gt;Fallibility&lt;&#x2F;h2&gt;
&lt;p&gt;There is one other issue with the proposal: we have no way to expose fallbility
of &lt;code&gt;try_join&lt;&#x2F;code&gt; semantics.  &lt;code&gt;try_join&lt;&#x2F;code&gt; allows short-circuiting a &lt;code&gt;join&lt;&#x2F;code&gt; operation
if any of the fallible futures returns a &lt;code&gt;Result::Error&lt;&#x2F;code&gt;. Right now we don&#x27;t have a way
to paramaterize the &lt;code&gt;await&lt;&#x2F;code&gt; over fallibility, and since we only have a single
&lt;code&gt;IntoFuture&lt;&#x2F;code&gt; implementation we&#x27;re stuck with just &lt;code&gt;join&lt;&#x2F;code&gt;, which is not ideal.
Perhaps using &lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;inside-rust&#x2F;2022&#x2F;07&#x2F;27&#x2F;keyword-generics.html&quot;&gt;keyword generics&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#kw-generics&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; we can find a way out of this.
After all: iterators face many of the same challenges today, since we can&#x27;t
just call &lt;code&gt;for ?..in&lt;&#x2F;code&gt; in loops. With keyword generics we might be able to
choose &lt;code&gt;try_join&lt;&#x2F;code&gt; semantics for constructs such as:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;kw-generics&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;&#x2F;sup&gt;
&lt;p&gt;Y. Wuyts, &lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;inside-rust&#x2F;2022&#x2F;07&#x2F;27&#x2F;keyword-generics.html&quot;&gt;“Announcing the Keyword Generics Initiative”&lt;&#x2F;a&gt;. (accessed Sep. 18, 2022).&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(Ok(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(Ok(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(a, b) = (a, b).await?; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; try_join await semantics
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This would infer that the want the fallible veriant of &lt;code&gt;IntoFuture&lt;&#x2F;code&gt; since we
call &lt;code&gt;?&lt;&#x2F;code&gt; on it after, and we&#x27;re in a fallible context. But it&#x27;s early on and
hard to say precisely how this would work. It seems encouraging though that
wanting fallible semantics for a construct is a shared problem across most of
the language, so there is a desire to solve it in a unified way.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post I&#x27;ve shown how Swift&#x27;s &lt;code&gt;async let&lt;&#x2F;code&gt; allows concurrent awaiting, how
we can implement it in Rust through &lt;code&gt;IntoFuture&lt;&#x2F;code&gt;, and what some of the
challenges with it might be. I think Swift has done a great job at showing how
convenient it is to be able to perform lightweight concurrent awaits, and I
think we can learn from their approach and make it our own.&lt;&#x2F;p&gt;
&lt;p&gt;Before starting this post I didn&#x27;t think too deeply about the similarities
between &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; and &lt;code&gt;IntoFuture&lt;&#x2F;code&gt;. But the more I look at them, the closer
they seem. The fact that we have &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; for most every container might give
us a hint for how we may want to think about container types. I&#x27;m not saying we
should go out and implement &lt;code&gt;IntoFuture&lt;&#x2F;code&gt; for &lt;code&gt;HashMap&lt;&#x2F;code&gt; - but for vec, array, and
tuples it definitely seems to make sense.&lt;&#x2F;p&gt;
&lt;p&gt;It seems that in terms of ordering we aren&#x27;t too far out from being able to
write an RFC for all of this either. I&#x27;m feeling pretty confident we&#x27;ve got the
basic subset done for fixed-length async concurrency operators. And with
&lt;code&gt;IntoFuture&lt;&#x2F;code&gt; exposing &lt;code&gt;join&lt;&#x2F;code&gt; semantics for arrays, tuples, and vectors, we can
make the main method of concurrency easy to use as well. We&#x27;ll have to see
exactly what we want to do about tuples wrt the design - since they can&#x27;t yet be
variadic. And we&#x27;ll want to wait on async traits to land first. But after 3
years of writing and experimentation on this topic, we don&#x27;t seem far out
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#yosh-opinion&quot;&gt;9&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; from finally being able to propose something concrete for
inclusion in the stdlib.  And I think that&#x27;s pretty exciting!&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;yosh-opinion&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;9&lt;&#x2F;sup&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;core&#x2F;future&#x2F;macro.join.html&quot;&gt;&lt;code&gt;join!&lt;&#x2F;code&gt;
macro&lt;&#x2F;a&gt; was added to the
stdlib a while back through a regular libs PR. But any stabilization of it
should be blocked on fleshing out a &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;91642#issuecomment-992773288&quot;&gt;complete concurrency model for async
Rust&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</description>
        </item>
        <item>
            <title>State Machines II: an enum-based design</title>
            <pubDate>Tue, 23 Aug 2022 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/state-machines-2/</link>
            <guid>https://blog.yoshuawuyts.com/state-machines-2/</guid>
            <description>&lt;p&gt;In the past I&#x27;ve written about &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;state-machines&quot;&gt;state machines&lt;&#x2F;a&gt; in Rust. And more recently I&#x27;ve
also written about &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;more-enum-types&#x2F;&quot;&gt;anonymous enums&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#sum-types&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; in Rust. I&#x27;ve been wondering what would
happen if the two interacted? I think the result could actually be quite nice,
and worth daydreaming about. In this post we&#x27;ll be discussing state machines,
the language features which could make them easier to use, and ways in which we
could push the ergonomics further.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;sum-types&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;&quot;anonymous enums&quot; are also known as &quot;sum types&quot;. There might be
subtle differences, but I&#x27;ll be using them interchangeably. For
the context of this post though, we assume that taking two members
of the same enum and putting them in a sum type results in a
sub-set of the original enum rather than creating a new enum with
two members. For the sake of brevity in this post, just assume
that works as intended.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;the-case-for-state-machines&quot;&gt;The case for state machines&lt;&#x2F;h2&gt;
&lt;p&gt;A lot of programming is about going from one state to another. We can do that
using conditionals statements, but as the state changes those conditions can be
tricky to reason about and in turn refactor. Instead it&#x27;s often more convenient
to use &lt;em&gt;state machines&lt;&#x2F;em&gt;: singular objects which represent all possible states
and their transitions. And in compiled languages specifically to use
&lt;em&gt;compiler-checked state machines&lt;&#x2F;em&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#nanostate&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;nanostate&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;See my JavaScript
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;choojs&#x2F;nanostate&quot;&gt;nanostate&lt;&#x2F;a&gt; library for an example of a
state machine library which is not checked by a compiler - instead performing
all checks at runtime.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Say we wanted to implement a basic green-orange-red traffic light that can also
flash. We can imagine the rules for transitions between states could be the
following:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Green can turn to orange&lt;&#x2F;li&gt;
&lt;li&gt;Orange can turn to red&lt;&#x2F;li&gt;
&lt;li&gt;Red can turn to green&lt;&#x2F;li&gt;
&lt;li&gt;Red can turn to flashing red &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#flashing&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Flashing red can turn to red&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;flashing&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;If you&#x27;ve never seen a traffic light blink red before:
this is common for traffic lights in the Netherlands. It can indicate that the
traffic control systems are malfunctioning. Or it can be used to indicate the
traffic lights have been disabled, which can be done late at night when there&#x27;s
hardly any traffic to be managed anyway.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;All states and their transitions can be represented by the following graph:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;state-machines-2&#x2F;graph.svg&quot; alt=&quot;A graph showing how all states point to each other&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;For the remainder of this post we&#x27;ll be implementing the rules of the graph
above. Our goal is to implement a compiler-checked state machine which can
inform us during compilation whether all our state transitions are valid, or if
we&#x27;ve accidentally written an invalid transition which we need to fix.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;representing-state-machines-in-rust-in-the-future&quot;&gt;Representing State Machines in Rust In The Future&lt;&#x2F;h2&gt;
&lt;p&gt;To read about how we can write compiler-checked state machines in Rust &lt;em&gt;today&lt;&#x2F;em&gt; you
can read &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;state-machines&quot;&gt;my previous post on state machines&lt;&#x2F;a&gt;. In this post I instead want to focus on
✨ the future ✨. How could we plausibly represent this in Rust by extending the
language. In the &quot;future directions&quot; section of the last post we wrote a state
machine without the blinky lights. Using &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;pull&#x2F;1450&quot;&gt;enum variants types&lt;&#x2F;a&gt; (not yet a
thing) combined with &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;44874&quot;&gt;arbitrary self-types&lt;&#x2F;a&gt; (also not
yet a thing), we could write the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! A traffic light without a flashing state.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Novel language features: enum-variant-types, arbitrary-self-types
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;State {
&lt;&#x2F;span&gt;&lt;span&gt;    Green,
&lt;&#x2F;span&gt;&lt;span&gt;    Orange,
&lt;&#x2F;span&gt;&lt;span&gt;    Red,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;State {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Green
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Orange {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Orange
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Orange) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Red {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Red
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Red) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Green
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; state = State::new(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; green
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; orange
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; red
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; green
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What I didn&#x27;t realize at the time I wrote my last post is that
this in effect acts like a form of &lt;em&gt;overloading&lt;&#x2F;em&gt;. Functionally the code we&#x27;ve
written isn&#x27;t different than writing a single &lt;code&gt;next&lt;&#x2F;code&gt; function which internally
updates the state. But instead we expose the state &lt;em&gt;externally&lt;&#x2F;em&gt;. The following
example will be written in valid Rust &lt;em&gt;today&lt;&#x2F;em&gt;, exposing the exact same
functionality as our last example — but with the state only observable
&lt;em&gt;internally&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! A traffic light without a flashing state.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Novel language features: none
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;State {
&lt;&#x2F;span&gt;&lt;span&gt;    Green,
&lt;&#x2F;span&gt;&lt;span&gt;    Orange,
&lt;&#x2F;span&gt;&lt;span&gt;    Red,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;State {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Green
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Green =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Orange,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Orange =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Red,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Red =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Green,
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; state = State::new(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; green
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; orange
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; red
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; green
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s continue with the internally observable state examples for a bit. Our
graph shows we need to support a &lt;code&gt;flashing&lt;&#x2F;code&gt; state, so we need to add that.
We need some way to trigger going into a flashing state, so we&#x27;ll add a new
method: &lt;code&gt;flash&lt;&#x2F;code&gt;. Not all states can transition into the flashing state, so we
need to make sure we can only go into it from &quot;red&quot; - which means we need to
panic if we attempt to transition into it from any other state:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! A traffic light with a flashing state.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Novel language features: none
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;State {
&lt;&#x2F;span&gt;&lt;span&gt;    Green,
&lt;&#x2F;span&gt;&lt;span&gt;    Orange,
&lt;&#x2F;span&gt;&lt;span&gt;    Red,
&lt;&#x2F;span&gt;&lt;span&gt;    Flashing,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;State {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Green
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Green =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Orange,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Orange =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Red,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Red =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Green,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Flashing =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Red,
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;flash&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            State::Red =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Flashing
&lt;&#x2F;span&gt;&lt;span&gt;            _ =&amp;gt; panic!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;only red can turn into flashing red&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;),
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; state = State::new(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; green
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; orange
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; red
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;flash&lt;&#x2F;span&gt;&lt;span&gt;();        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; flashing
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; red
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is not ideal: we now have added a runtime check to a state machine which
was checked entirely during compilation before. The reason a runtime check
is needed is because by adding a method which isn&#x27;t available on all types,
the &lt;em&gt;internal&lt;&#x2F;em&gt; state becomes observable &lt;em&gt;externally&lt;&#x2F;em&gt;. And the Rust language
lacks the tools to conveniently represent this &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#argue&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;argue&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;Yes, I know we can refactor the whole thing and use traits and
generics to hack together something which gives us similar semantics. I&#x27;ve shown
how to do that in previous posts. The point of this post is not &lt;em&gt;&quot;can we
represent state machines using Rust&#x27;s type system&quot;&lt;&#x2F;em&gt; (yes we can), but &lt;em&gt;&quot;which
language features are we lacking to make it easy to represent state machines in
Rust&#x27;s type system&quot;&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;So let&#x27;s try and rewrite this again using enum variant types and arbitrary
self-types. Here the caller knows exactly what state the enum is in, and we can
more precisely represent the states and state transitions:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! A traffic light with a flashing state.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Novel language features: enum-variant-types, arbitrary-self-types
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;State {
&lt;&#x2F;span&gt;&lt;span&gt;    Green,
&lt;&#x2F;span&gt;&lt;span&gt;    Orange,
&lt;&#x2F;span&gt;&lt;span&gt;    Red,
&lt;&#x2F;span&gt;&lt;span&gt;    Flashing,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;State {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Green
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Orange {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Orange
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Orange) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Red {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Red
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Red) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Green
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; new
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Flashing) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Red {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Red
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; new
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;flash&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Red) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Flashing {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Flashing
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; state = State::new(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; green
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; orange
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; red
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;flash&lt;&#x2F;span&gt;&lt;span&gt;();        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; flashing
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; red
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This would allow us to correctly model and validate the entire state graph at
compile-time, without needing to resort to any runtime checks. Yay us!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ergonomics-overview&quot;&gt;Ergonomics: Overview&lt;&#x2F;h2&gt;
&lt;p&gt;Hopefully folks can see the benefit of being able to model state transitions
solely through the type system. Obviously there are other ways of authoring
compiler-checked state machines today - but that&#x27;s not the point of this post.
What we&#x27;re trying to think about is how we can do so in a way which feels
&lt;em&gt;simple&lt;&#x2F;em&gt; and dare I even say, &lt;em&gt;intuitive&lt;&#x2F;em&gt; for people to use.&lt;&#x2F;p&gt;
&lt;p&gt;I think what we&#x27;ve shown so far is pretty good. But it has a few shortcomings,
namely:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;It&#x27;s pretty verbose to individually write each transition&lt;&#x2F;li&gt;
&lt;li&gt;What happens when we have more than one valid return state from a function?&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Okay, so bear with me for a sec here. In the graph each line goes from a &lt;em&gt;source&lt;&#x2F;em&gt;
to a &lt;em&gt;destination&lt;&#x2F;em&gt;. In the code the sources are represented by the self-types,
and the destinations are represented by the return types. This means that any
node in the graph with more than arrow pointing from or to it could potentially
benefit from refactoring. In the graph above there are instances of this:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;orange&lt;&#x2F;code&gt; and &lt;code&gt;flashing&lt;&#x2F;code&gt; point to &lt;code&gt;red&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;red&lt;&#x2F;code&gt; points to both &lt;code&gt;green&lt;&#x2F;code&gt; and &lt;code&gt;flashing&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;For any type system enthusiasts reading this post: yes we&#x27;re going to be
talking about representing powerset enums natively using Rust&#x27;s typesystem
here &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#powerset&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;powerset&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;For everyone who isn&#x27;t a type system enthusiast and doesn&#x27;t know
about &quot;powerset enums&quot;, it&#x27;s basically just &quot;subsets of enums&quot;. Instead of
declaring that a method can return &lt;em&gt;all&lt;&#x2F;em&gt; variants in an enum, using powersets we
can declare that a method can only return a specific subset. Check out the
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;powerset-enum&#x2F;latest&#x2F;powerset_enum&#x2F;&quot;&gt;powerset_enum crate&lt;&#x2F;a&gt; to read more about it. Or alternatively you can keep
reading, because that&#x27;s basically what we&#x27;ll be implementing.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;ergonomics-merging-self-types&quot;&gt;Ergonomics: Merging Self-Types&lt;&#x2F;h2&gt;
&lt;p&gt;Now let&#x27;s start with the first one: &quot;orange&quot; and &quot;flashing&quot; both point to &quot;red&quot;. So
far we&#x27;ve been talking about arbitrary self-types as a feature. But there are
ideas floating around about expanding this for structs, called: &lt;a href=&quot;https:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2021&#x2F;11&#x2F;05&#x2F;view-types&#x2F;&quot;&gt;view types&lt;&#x2F;a&gt;.
What this allows you to do is inform the borrow checker we don&#x27;t actually need
access to the entire struct - we only need access to parts of it. So we can hold
multiple mutable borrows on the same struct as long as the fields don&#x27;t overlap.&lt;&#x2F;p&gt;
&lt;p&gt;Now what if we had the equivalent of these struct &quot;views&quot; but for enums. Instead
of &quot;viewing&quot; subsets of fields, we&#x27;d be able to &quot;view&quot; subsets of enums. Now
let&#x27;s make up a syntax to show what we mean. In patterns we already have &lt;code&gt;Foo | Bar&lt;&#x2F;code&gt; to represent multiple patterns, so let&#x27;s reuse that here:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; before
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;State {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Orange) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Red {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Red
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Flashing) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Red {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Red
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; after
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;State {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Orange | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Flashing) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Red {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Red
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I know many of you will likely have opinions about the syntax, but let&#x27;s not
focus on that for a minute. Instead I want to focus your attention attention on
the semantics at play here: it would bring the same pattern semantics as used in
&lt;code&gt;match&lt;&#x2F;code&gt; statements to methods, which I believe should feel a lot more natural?&lt;&#x2F;p&gt;
&lt;p&gt;Riffing time. There are some real questions about &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;safe-pin-projections-through-view-types&#x2F;&quot;&gt;what syntax view types should use&lt;&#x2F;a&gt;.
Niko&#x27;s post suggests something like &lt;code&gt;&amp;amp;{golden_tickets} self&lt;&#x2F;code&gt;. But what if
instead we chose to reuse the pattern syntax for the &lt;code&gt;self&lt;&#x2F;code&gt; types &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#eholk&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; -
which could yield us something like &lt;code&gt;&amp;amp;Self { golden_tickets, .. }&lt;&#x2F;code&gt;. This would
reuse the pattern-destructuring syntax. Which is similar to what we&#x27;re doing
here: reusing the pattern enum matching syntax. It feels like there might be
something to it?&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;eholk&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;My colleague &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;theinedibleholk&quot;&gt;eric&lt;&#x2F;a&gt; suggested
exploring this direction a while back. And I actually quite like it! (Direct any
credit to Eric, but blame to me please. I&#x27;ve definitely run with this way past
what he likely intended.)&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;The compiler knows that the possible members of &lt;code&gt;self&lt;&#x2F;code&gt; in the example (&quot;orange&quot;,
&quot;flashing&quot;) are only a subset of all members in &lt;code&gt;State&lt;&#x2F;code&gt;. What if the compiler
actually used this information in the function body too? That would mean matching
on &lt;code&gt;self&lt;&#x2F;code&gt; would only need to account for the &lt;em&gt;possible&lt;&#x2F;em&gt; cases rather than &lt;em&gt;all&lt;&#x2F;em&gt;
cases:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Orange =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Flashing =&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; no other cases need matching!
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This isn&#x27;t particularly relevant yet for the simple traffic light example we&#x27;re
dealing with here, but definitely becomes a lot more relevant when working with
real-world code. No longer needing to &lt;code&gt;panic!&lt;&#x2F;code&gt; for branches you know can&#x27;t be
reached anyway would make code both simpler and faster, which is a pretty big deal!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ergonomics-merging-return-types&quot;&gt;Ergonomics: Merging Return Types&lt;&#x2F;h2&gt;
&lt;p&gt;The second case is: &lt;em&gt;&quot;red can point to both green and flashing&quot;&lt;&#x2F;em&gt;. This one will be a bit
harder to reason about because instead of taking multiple different parameters
we&#x27;re trying to &lt;em&gt;return&lt;&#x2F;em&gt; multiple parameters. This means the compiler can
no longer &lt;em&gt;statically&lt;&#x2F;em&gt; know which variant we have, and instead we have to
perform runtime matching to figure that out. Right now the code we have looks
like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; before
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;State {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Red) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Green
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;flash&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Red) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Flashing {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Flashing
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We have two different methods which take &lt;code&gt;Self::Red&lt;&#x2F;code&gt; and return a type. For
argument&#x27;s sake say we wanted a single method with took some data to determine
whether we should go to &lt;code&gt;green&lt;&#x2F;code&gt; or &lt;code&gt;flashing&lt;&#x2F;code&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#data&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. This could then look
something like this:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;data&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;&quot;For argument&#x27;s sake&quot; means I couldn&#x27;t come up with a good example. So
this is def a cop-out.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; after
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;State {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Red, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: Data) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Flashing {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;validate_data&lt;&#x2F;span&gt;&lt;span&gt;(data) {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Green
&lt;&#x2F;span&gt;&lt;span&gt;        } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Flashing
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Again, the syntax is not really the point. The idea here is though that just
like in the earlier example the returned value would be known to be a subset of
&lt;code&gt;Self&lt;&#x2F;code&gt;: it would still register as the &lt;code&gt;State&lt;&#x2F;code&gt; enum, but the only two accessible
members are &lt;code&gt;Green&lt;&#x2F;code&gt; and &lt;code&gt;Flashing&lt;&#x2F;code&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#syntax&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;syntax&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;&#x2F;sup&gt;
&lt;p&gt;Maybe a better way to signal this would be to use something like
&lt;code&gt;-&amp;gt; Self { Green | Flashing }&lt;&#x2F;code&gt; as syntax? Idk,, I&#x27;m focusing more on semantics than
syntax right now.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;On the usage side things would change too: we could no longer statically know
which state we&#x27;re in. All we know is that the state is either green or flashing.
This leads to some very real questions: should we be able to then call &lt;code&gt;next&lt;&#x2F;code&gt;
again to get to &lt;code&gt;orange | red&lt;&#x2F;code&gt;?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; state = State::new(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; green
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; orange
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; red
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(data);     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; green | flashing       - ok I guess?
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; orange | red           - uhhh,,
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(?data);    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; green | red | flashing - x_x
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Once we&#x27;re in this state, we have different &lt;code&gt;next&lt;&#x2F;code&gt; methods. How do we decide how
we should call them? Even if we can answer this question, the semantics of this
seem pretty complex and hard to teach. So instead I propose we apply some
basic rules here to simplify usage:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Once a variable is assigned to a single enum-member-as-value, it can only be
re-assigned to other single values and vice-versa.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#rule&quot;&gt;9&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Methods with the same name on the same enum need to have the same &quot;base&quot;
(type from which a view is derived) signature.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;rule&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;9&lt;&#x2F;sup&gt;
&lt;p&gt;Maybe this rule could be relaxed over time? I&#x27;m not sure; it seems very
graph-problem-y, and I don&#x27;t know if there are any great solutions to this.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;The first rule would disallow assigning &lt;code&gt;green | flashing&lt;&#x2F;code&gt; to &lt;code&gt;state&lt;&#x2F;code&gt;. Instead
we&#x27;d need to &lt;code&gt;match&lt;&#x2F;code&gt; to know which variant we have, and go from there:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Never assign an enum view-type to `state`. This requires matching on the data
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! until we&amp;#39;ve extraced a single member. Assume we wait for conditions to change
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! between calls to `state.next`.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; state = State::new();                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; green
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();                            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; orange
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();                            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; red
&lt;&#x2F;span&gt;&lt;span&gt;    state = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;handle_flash&lt;&#x2F;span&gt;&lt;span&gt;(state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;data), &amp;amp;data);  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; green
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Keep looping until we hit a green state.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;handle_flash&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;state&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;State::&lt;&#x2F;span&gt;&lt;span&gt;Green | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;State::&lt;&#x2F;span&gt;&lt;span&gt;Flashing, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;Data) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;State::&lt;&#x2F;span&gt;&lt;span&gt;Green {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; state {
&lt;&#x2F;span&gt;&lt;span&gt;        State::Green =&amp;gt; State::Green,
&lt;&#x2F;span&gt;&lt;span&gt;        State::Flashing =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;            state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();              &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; red
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_green&lt;&#x2F;span&gt;&lt;span&gt;(state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;data), &amp;amp;data) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; green
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are a bunch of assumptions baked in here - not in the least that an anonymous enum of
&lt;code&gt;State::Green | State::Flashing&lt;&#x2F;code&gt; can be passed to an enum view-type matching the
same members. But we&#x27;re not doing details in this post. We&#x27;re doing vibes. Yeehaw.&lt;&#x2F;p&gt;
&lt;p&gt;Okay, so for the second rule we&#x27;re proposing: &lt;em&gt;methods with the same name on the same enum
should share the same base signature&lt;&#x2F;em&gt;. This means that methods which return a
&lt;em&gt;view&lt;&#x2F;em&gt; of some enum or struct are fine - because they&#x27;re the same &quot;base&quot; type.
But having different methods with different signatures like we&#x27;ve done here with
&lt;code&gt;next(data)&lt;&#x2F;code&gt; would be a no-no. This would allow us to keep thinking about
methods which take or return enum views as a form of specialization.&lt;&#x2F;p&gt;
&lt;p&gt;That last point is perhaps not strictly required, but it has the benefit of
making the enum feel more &lt;em&gt;consistent&lt;&#x2F;em&gt;. And it could lead allow for
specialization-like behavior where if you implement the same method for all enum
members, it then becomes unconditionally available on the entire enum - since it
can be called regardless of which state you&#x27;re in, even if it yields different
behavior. But on a more intuitive level: it feels pretty weird that
&lt;code&gt;self.next()&lt;&#x2F;code&gt; sometimes takes an argument and sometimes doesn&#x27;t. It kind of
feels like parameter overloading like it&#x27;s done in other languages, and Rust
kind of steers clear of that. So it feels better to just enforce that methods
with the same name on the same enum need to take the same arguments - even if we
can wiggle around with view-types and sub-types a little.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tying-it-together&quot;&gt;Tying It Together&lt;&#x2F;h2&gt;
&lt;p&gt;Phew, that&#x27;s been a ride. The last section has been a lot about what &lt;em&gt;not&lt;&#x2F;em&gt; to
do. So let&#x27;s show an example of how things might look when we put them all
together. Let&#x27;s start with what we had before, but slightly adapted to make the
&lt;code&gt;flash&lt;&#x2F;code&gt; case conditional:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! A traffic light with a flashing state.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Novel language features: enum-variant-types, arbitrary-self-types
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;State {
&lt;&#x2F;span&gt;&lt;span&gt;    Green,
&lt;&#x2F;span&gt;&lt;span&gt;    Orange,
&lt;&#x2F;span&gt;&lt;span&gt;    Red,
&lt;&#x2F;span&gt;&lt;span&gt;    Flashing,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;State {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Green
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Orange {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Orange
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Orange) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Red {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Red
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Red) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Green
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; new
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Flashing) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Red {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Red
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; new
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;flash&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Red) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Flashing {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Flashing
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; state = State::new(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; green
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; orange
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; red
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;validate_data&lt;&#x2F;span&gt;&lt;span&gt;(data) {
&lt;&#x2F;span&gt;&lt;span&gt;            state = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; green
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; handle green
&lt;&#x2F;span&gt;&lt;span&gt;        } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            state = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;flash&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; flashing
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; handle flashing
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now if we translate that to our enum views variant, we&#x27;re able to inline the
conditional statement into the enum. And together with the arbitrary self enum
pattern syntax, the overall code is a lot more trimmed. And especially the usage
should feel a bit more natural:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! A traffic light with a flashing state.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Novel language features: enum-variant-types, arbitrary-self-types,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;!                          enum-view-types, enum-sum-types
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;State {
&lt;&#x2F;span&gt;&lt;span&gt;    Green,
&lt;&#x2F;span&gt;&lt;span&gt;    Orange,
&lt;&#x2F;span&gt;&lt;span&gt;    Red,
&lt;&#x2F;span&gt;&lt;span&gt;    Flashing,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;State {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Green
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Orange {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Orange
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Orange | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Flashing) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Red {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Red
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; New: Inlines the logic of the previous example to decide whether to go
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;      from &amp;quot;red&amp;quot; to &amp;quot;green&amp;quot; or &amp;quot;flashing&amp;quot;.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;try_next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Red, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: Data) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Flashing {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;validate_data&lt;&#x2F;span&gt;&lt;span&gt;(data) {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Green
&lt;&#x2F;span&gt;&lt;span&gt;        } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Flashing
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; state = State::new();   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; green
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; orange
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; red
&lt;&#x2F;span&gt;&lt;span&gt;    state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_next&lt;&#x2F;span&gt;&lt;span&gt;(data) {
&lt;&#x2F;span&gt;&lt;span&gt;        State::Green =&amp;gt; {},         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; handle green
&lt;&#x2F;span&gt;&lt;span&gt;        State::Flashing =&amp;gt; {},      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; handle flashing
&lt;&#x2F;span&gt;&lt;span&gt;    };
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve looked at how using &quot;enum variant types&quot;, &quot;enum sum
types&quot;, and &quot;enum view types&quot; could allow us to make state machines at the type
level in Rust easier to author and more ergonomic. The example we&#x27;ve used here
has been a variation of a basic traffic light. But despite that we expect that
it should be possible to adopt the patterns and features shown here to state
machines in general.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Challenges&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It seems that taking enums as self-types should be relatively straight-forward.
But returning anonymous enums is more complicated. I came up with some rules to
help circumvent some of the sharp edges, but I feel those probably could use
some more thought. Maybe folks reading this have some insights on it?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Making Enums More Useful&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Also as my colleague &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sivadeilra&quot;&gt;Arlie&lt;&#x2F;a&gt; pointed out during a recent chat: having
enums-as-types would be really beneficial for other reasons too. Take for
example the &lt;code&gt;syn&lt;&#x2F;code&gt; crate &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#arlie-blame&quot;&gt;10&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;: the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;syn&#x2F;latest&#x2F;syn&#x2F;enum.WherePredicate.html&quot;&gt;&lt;code&gt;WherePredicate&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; has a member &lt;code&gt;Type&lt;&#x2F;code&gt; which
contains a struct called &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;syn&#x2F;latest&#x2F;syn&#x2F;struct.PredicateType.html&quot;&gt;&lt;code&gt;PredicateType&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. The reason why we have a separate
struct instead of just inlining the data in the enum member, is because members
can&#x27;t be used as types. So if we want to author functions which operate on the
data in &lt;code&gt;WherePredicate::Type&lt;&#x2F;code&gt;, we &lt;em&gt;need&lt;&#x2F;em&gt; to create a separate struct &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#uses&quot;&gt;11&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.
This makes record-enums less useful than their struct counterparts, and
complicates the API surface area of crates.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;arlie-blame&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;10&lt;&#x2F;sup&gt;
&lt;p&gt;I picked this as an example, so if there are actually different
instances where &lt;code&gt;PredicateType&lt;&#x2F;code&gt; is used - that&#x27;s on me. I&#x27;m not an expert on
&lt;code&gt;syn&lt;&#x2F;code&gt; so details may be wrong. But I hope the example is clear enough that at
least the point comes across: because this does happen in a lot of places.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;uses&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;11&lt;&#x2F;sup&gt;
&lt;p&gt;Ideally we should only create need to create separate structs if we
want to reuse types between enums. That&#x27;s not the case today.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;strong&gt;Structural Typing and Errors&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;While we&#x27;re on the topic of anonymous enums in general: another important use
case for it would be for error handling. Anonymous enums provide us with
structural typing for enums &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#structural&quot;&gt;12&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, which allows for convenient
composition of error types. Say we have a &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;string&#x2F;type.ParseError.html&quot;&gt;&lt;code&gt;ParseError&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;io&#x2F;struct.Error.html&quot;&gt;&lt;code&gt;io::Error&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, a
function should just be able to specify &lt;code&gt;-&amp;gt; Result&amp;lt;T, ParseError | io::Error&amp;gt;&lt;&#x2F;code&gt;.
But more importantly: we should be able to specify which error variants can be
returned. This is a bit harder with &lt;code&gt;io::Error&lt;&#x2F;code&gt; specifically because of how it&#x27;s
constructed. But would work great when using errors returned by &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;thiserror&#x2F;latest&#x2F;thiserror&#x2F;&quot;&gt;&lt;code&gt;thiserror&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
I&#x27;ve been meaning to write about error handling ever since I posted &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;error-handling-survey&quot;&gt;my error
handling survey&lt;&#x2F;a&gt; three years ago. Maybe I&#x27;ll do that later this year.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;structural&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;12&lt;&#x2F;sup&gt;
&lt;p&gt;You can think of &quot;structural typing&quot; as &quot;matching on the shape&quot;
instead of &quot;matching on the type&quot;. Matching on a tuple with &lt;code&gt;(first, second)&lt;&#x2F;code&gt; is
structural: we don&#x27;t care what types are in the tuple, we mostly care about the
shape. It still needs to type-check of course, but combined with type inference
it can give us a lot of flexibility. For example TypeScript&#x27;s type system is
structural, and in turn provides a lot of flexibility.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;strong&gt;View Types&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Also, while writing this post I realized that being able to use enum variants
as self-types is kind of analogous to view types for structs. Both carve out
subsets of their base type, but for different purposes. Which makes sense
because they&#x27;re actually different. But as a general trend the implications seem
fun: by more precisely articulating which sub-types we use, the compiler can
allow more code to function. I think the reason for that is that function
boundaries act as strict guards for what&#x27;s allowed, and as a rule are also
pretty coarse-grained. By making the more expressive, the compiler becomes less
strict, and in turn more code can be allowed. It really does feel like view
types and the like might represent a generational leap akin to &lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;2022&#x2F;08&#x2F;05&#x2F;nll-by-default.html&quot;&gt;NLL&lt;&#x2F;a&gt; in terms of
general language ergonomics. I think it&#x27;s interesting to think about what else
could be loosened within the framework of Rust&#x27;s existing semantics.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Goals of this post&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To re-iterate: this post is intentionally incomplete. I&#x27;ve knowingly glossed
over details, and left pieces out. The goal of the post was to show what the
&lt;em&gt;outcomes&lt;&#x2F;em&gt; we could have if we combined some features folks are thinking about
anyway. Together with a personal goal to not spend months writing about this,
because I actually should be working on diffferent things. Rust&#x27;s
roadmap is always a balance of team prioritization and personal interests; so
showing what can be achieved by combining several features might lower the bar
to make the case these features would be useful, or perhaps even get people
interested in working on this.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Wrapping up&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, that&#x27;s probably enough discussion for now. This post was a massive
procrastination from writing another post on &quot;halt points&quot;, which I&#x27;ve finished
drafting and am currently editing. This was is mostly thoughts which have been
stewing in the back of my mind after talking with colleages at work about state
machines, type systems, and more accurately modeling programs. Thanks for reading!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Announcing the Keyword Generics Initiative</title>
            <pubDate>Wed, 27 Jul 2022 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/announcing-the-keyword-generics-initiative/</link>
            <guid>https://blog.yoshuawuyts.com/announcing-the-keyword-generics-initiative/</guid>
            <description>&lt;blockquote&gt;
&lt;p&gt;This post is a mirror of &lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;inside-rust&#x2F;2022&#x2F;07&#x2F;27&#x2F;keyword-generics.html&quot;&gt;the post published to the Inside Rust
blog&lt;&#x2F;a&gt;.
If you want to read an earlier iteration of the ideas described in this post,
check out the post on
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-overloading&#x2F;&quot;&gt;Async Overloading&lt;&#x2F;a&gt;,
written about a year earlier.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;We (&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;oli-obk&quot;&gt;Oli&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nikomatsakis&quot;&gt;Niko&lt;&#x2F;a&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yoshuawuyts&quot;&gt;Yosh&lt;&#x2F;a&gt;) are excited to announce the start of the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;keyword-generics-initiative&quot;&gt;Keyword
Generics Initiative&lt;&#x2F;a&gt;, a new initiative &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#initiative&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; under the purview of
the language team. We&#x27;re officially just a few weeks old now, and in this post
we want to briefly share why we&#x27;ve started this initiative, and share some
insight on what we&#x27;re about.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;initiative&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Rust governance terminology can sometimes get confusing. An
&quot;initiative&quot; in Rust parlance is different from a &quot;working group&quot; or &quot;team&quot;.
Initiatives are intentionally limited: they exist to explore, design, and
implement specific pieces of work - and once that work comes to a close, the
initiative will wind back down. This is different from, say, the lang team -
which essentially carries a &lt;code&gt;&#x27;static&lt;&#x2F;code&gt; lifetime - and whose work does
not have a clearly defined end.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;a-missing-kind-of-generic&quot;&gt;A missing kind of generic&lt;&#x2F;h2&gt;
&lt;p&gt;One of Rust&#x27;s defining features is the ability to write functions which are
&lt;em&gt;generic&lt;&#x2F;em&gt; over their input types. That allows us to write a function once,
leaving it up to the compiler to generate the right implementations for us.&lt;&#x2F;p&gt;
&lt;p&gt;Rust allows you to be generic over types - it does not allow you to be generic
over other things that are usually specified by keywords. For example, whether a
function is async, whether a function can fail or not, whether a function is
const or not, etc.&lt;&#x2F;p&gt;
&lt;p&gt;The post &lt;a href=&quot;https:&#x2F;&#x2F;journal.stuffwithstuff.com&#x2F;2015&#x2F;02&#x2F;01&#x2F;what-color-is-your-function&#x2F;&quot;&gt;&quot;What color is your function&quot;&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#color&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; describes what happens
when a language introduces async functions, but with no way to be generic over
them:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I will take async-await over bare callbacks or futures any day of the week.
But we’re lying to ourselves if we think all of our troubles are gone. As soon
as you start trying to write higher-order functions, or reuse code, you’re
right back to realizing color is still there, bleeding all over your codebase.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This isn&#x27;t just limited to async though, it applies to all modifier keywords -
including ones we may define in the future. So we&#x27;re looking to fill that gap
by exploring something we call &quot;keyword generics&quot; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#name&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;: the ability to be
generic over keywords such as &lt;code&gt;const&lt;&#x2F;code&gt; and &lt;code&gt;async&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;color&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;R. Nystrom, “What Color is Your Function?,” Feb. 01, 2015.
https:&#x2F;&#x2F;journal.stuffwithstuff.com&#x2F;2015&#x2F;02&#x2F;01&#x2F;what-color-is-your-function&#x2F;
(accessed Apr. 06, 2022).&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;name&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;The longer, more specific name would be: &quot;keyword modifier generics&quot;.
We&#x27;ve tried calling it that, but it&#x27;s a bit of a mouthful. So we&#x27;re just
sticking with &quot;keyword generics&quot; for now, even if the name for this feature may
end up being called something more specific in the reference and documentation.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;To give you a quick taste of what we&#x27;re working on, this is roughly how we
imagine you may be able to write a function which is generic over &quot;asyncness&quot;
in the future:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Please note that this syntax is entirely made up, just so we can use something
in examples. Before we can work on syntax we need to finalize the semantics,
and we&#x27;re not there yet. This means the syntax will likely be subject to
change over time.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;async&amp;lt;A&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Read {
&lt;&#x2F;span&gt;&lt;span&gt;    async&amp;lt;A&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    async&amp;lt;A&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read_to_string&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; String) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; { ... }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Read from a reader into a string.
&lt;&#x2F;span&gt;&lt;span&gt;async&amp;lt;A&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read_to_string&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;reader&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; impl Read * A) -&amp;gt; std::io::Result&amp;lt;String&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; string = String::new();
&lt;&#x2F;span&gt;&lt;span&gt;    reader.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_to_string&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; string).await?;
&lt;&#x2F;span&gt;&lt;span&gt;    string
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This function introduces a &quot;keyword generic&quot; parameter into the function of &lt;code&gt;A&lt;&#x2F;code&gt;.
You can think of this as a flag which indicates whether the function is being
compiled in an async context or not. The parameter &lt;code&gt;A&lt;&#x2F;code&gt; is forwarded to the &lt;code&gt;impl Read&lt;&#x2F;code&gt;, making that conditional on &quot;asyncness&quot; as well.&lt;&#x2F;p&gt;
&lt;p&gt;In the function body you can see a &lt;code&gt;.await&lt;&#x2F;code&gt; call. Because &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-cancellation-1&#x2F;&quot;&gt;the &lt;code&gt;.await&lt;&#x2F;code&gt; keyword
marks cancellation sites&lt;&#x2F;a&gt; we unfortunately can&#x27;t just infer them
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#cancellation&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Instead we require them to be written for when the code is
compiled in async mode, but are essentially reduced to a no-op in non-async
mode.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;cancellation&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;No really, we can&#x27;t just infer them - and it may not be as
simple as omitting all &lt;code&gt;.await&lt;&#x2F;code&gt; calls either. The Async WG is working through
the full spectrum of cancellation sites, async drop, and more. But for now we&#x27;re
working under the assumption that &lt;code&gt;.await&lt;&#x2F;code&gt; will remain relevant going forward.
And even in the off chance that it isn&#x27;t, fallibility has similar requirements
at the call site as async does.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;We still have lots of details left to figure out, but we hope this at least
shows the general &lt;em&gt;feel&lt;&#x2F;em&gt; of what we&#x27;re going for.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-peek-at-the-past-horrors-before-const&quot;&gt;A peek at the past: horrors before const&lt;&#x2F;h2&gt;
&lt;p&gt;Rust didn&#x27;t always have &lt;code&gt;const fn&lt;&#x2F;code&gt; as part of the language. A long long long long
long time ago (2018) we had to write a regular function for runtime computations
and associated const of generic type logic for compile-time computations. As an
example, to add the number &lt;code&gt;1&lt;&#x2F;code&gt; to a constant provided to you, you had to write
(&lt;a href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=stable&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=50e818b79b8af322ed4384d3c33e9773&quot;&gt;playground&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Const&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VAL&lt;&#x2F;span&gt;&lt;span&gt;: T;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; `42` as a &amp;quot;const&amp;quot; (type) generic:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;FourtyTwo;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Const&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;FourtyTwo {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VAL&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32 &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;42&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; `C` -&amp;gt; `C + 1` operation:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;AddOne&amp;lt;C: Const&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;(C);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;C: Const&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; Const&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;AddOne&amp;lt;C&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VAL&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32 &lt;&#x2F;span&gt;&lt;span&gt;= C::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VAL &lt;&#x2F;span&gt;&lt;span&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;AddOne::&amp;lt;FourtyTwo&amp;gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VAL
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Today this is as easy as writing a &lt;code&gt;const fn&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;add_one&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    i + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add_one&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;42&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The interesting part here is that you can also just call this function in
runtime code, which means the implementation is shared between both &lt;code&gt;const&lt;&#x2F;code&gt;
(CTFE&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#ctfe&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;) and non-&lt;code&gt;const&lt;&#x2F;code&gt; (runtime) contexts.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;ctfe&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;CTFE stands for &quot;Compile Time Function Execution&quot;: &lt;code&gt;const&lt;&#x2F;code&gt; functions
can be evaluated during compilation, which is implemented using a Rust
interpreter (miri).&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;memories-of-the-present-async-today&quot;&gt;Memories of the present: async today&lt;&#x2F;h2&gt;
&lt;p&gt;People write duplicate code for async&#x2F;non-async with the only difference being
the &lt;code&gt;async&lt;&#x2F;code&gt; keyword. A good example of that code today is &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;latest&#x2F;async_std&#x2F;&quot;&gt;&lt;code&gt;async-std&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which
duplicates and translates a large part of the stdlib&#x27;s API surface to be async
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#async-std&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. And because the Async WG has made it an explicit goal to &lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;wg-async&#x2F;vision&#x2F;how_it_feels.html&quot;&gt;bring
async Rust up to par with non-async Rust&lt;&#x2F;a&gt;, the issue of code
duplication is particularly relevant for the Async WG as well. Nobody on the
Async WG seems particularly keen on proposing we add a second instance of just
about every API currently in the stdlib.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;async-std&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;Some limitations in &lt;code&gt;async-std&lt;&#x2F;code&gt; apply: async Rust is missing async
&lt;code&gt;Drop&lt;&#x2F;code&gt;, async traits, and async closures. So not all APIs could be duplicated.
Also &lt;code&gt;async-std&lt;&#x2F;code&gt; explicitly didn&#x27;t reimplement any of the collection APIs to be
async-aware, which means users are subject to the &quot;sandwich problem&quot;. The
purpose of &lt;code&gt;async-std&lt;&#x2F;code&gt; was to be a proving ground to test whether creating
an async mirror of the stdlib would be possible: and it&#x27;s proven that it is, as
far as was possible with missing language features.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;We&#x27;re in a similar situation with &lt;code&gt;async&lt;&#x2F;code&gt; today as &lt;code&gt;const&lt;&#x2F;code&gt; was prior to 2018.
Duplicating entire interfaces and wrapping them in &lt;code&gt;block_on&lt;&#x2F;code&gt; calls is the
approach taken by e.g. the &lt;code&gt;mongodb&lt;&#x2F;code&gt;
[&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;mongodb&#x2F;latest&#x2F;mongodb&#x2F;index.html&quot;&gt;async&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;mongodb&#x2F;latest&#x2F;mongodb&#x2F;sync&#x2F;index.html&quot;&gt;non-async&lt;&#x2F;a&gt;], &lt;code&gt;postgres&lt;&#x2F;code&gt;
[&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio-postgres&#x2F;latest&#x2F;tokio_postgres&#x2F;index.html&quot;&gt;async&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;postgres&#x2F;latest&#x2F;postgres&#x2F;&quot;&gt;non-async&lt;&#x2F;a&gt;], and &lt;code&gt;reqwest&lt;&#x2F;code&gt;
[&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;reqwest&#x2F;latest&#x2F;reqwest&#x2F;&quot;&gt;async&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;reqwest&#x2F;latest&#x2F;reqwest&#x2F;blocking&#x2F;index.html&quot;&gt;non-async&lt;&#x2F;a&gt;] crates:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Async functionality like this would typically be exposed from a crate &amp;quot;foo&amp;quot;:
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Bar { 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; async implementation goes here
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; And a sync counterpart would typically be exposed from a crate
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; named &amp;quot;blocking_foo&amp;quot; or a submodule on the original crate as
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; &amp;quot;foo::blocking&amp;quot;. This wraps the async code in a `block_on` call:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Bar {
&lt;&#x2F;span&gt;&lt;span&gt;    futures::executor::block_on(foo::bar())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This situation is not ideal. Instead of using the host&#x27;s synchronous syscalls,
we&#x27;re now going through an async runtime to get the same results - something
which is often not zero-cost. But more importantly, it&#x27;s rather hard to
keep both a sync and async API version of the same crate in, err, sync with each
other. Without automation it&#x27;s really easy for the two APIs to get out of sync,
leading to mismatched functionality.&lt;&#x2F;p&gt;
&lt;p&gt;The ecosystem has come up with some solutions to this, perhaps most notably the
proc-macro based &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;maybe-async&#x2F;0.2.6&#x2F;maybe_async&#x2F;&quot;&gt;&lt;code&gt;maybe-async&lt;&#x2F;code&gt; crate&lt;&#x2F;a&gt;.  Instead of writing two
separate copies of &lt;code&gt;foo&lt;&#x2F;code&gt;, it generates a sync and async variant for you:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;maybe_async&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Bar { ... }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While being useful, the macro has clear limitations with respect to diagnostics
and ergonomics. That&#x27;s absolutely not an issue with the crate, but an inherent
property of the problem it&#x27;s trying to solve. Implementing a way to be generic
over the &lt;code&gt;async&lt;&#x2F;code&gt; keyword is something which will affect the language in many
ways, and a type system + compiler will be better equipped to handle it than
proc macros reasonably can.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-taste-of-trouble-the-sandwich-problem&quot;&gt;A taste of trouble: the sandwich problem&lt;&#x2F;h2&gt;
&lt;p&gt;A pervasive issue in existing Rust is the &lt;em&gt;sandwich&lt;&#x2F;em&gt; problem. It occurs when a
type passed into an operation wants to perform control flow not supported by the
type it&#x27;s passed into. Thus creating a &lt;em&gt;sandwich&lt;&#x2F;em&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#dilemma&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; The classic example
is a &lt;code&gt;map&lt;&#x2F;code&gt; operation:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;dilemma&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;Not to be confused with the higher-order &lt;em&gt;sandwich dilemma&lt;&#x2F;em&gt; which is
when you look at the sandwich problem and attempt to determine whether the
sandwich is two slices of bread with a topping in between, or two toppings with
a slice of bread in between. Imo the operation part of the problem feels more
&lt;em&gt;bready&lt;&#x2F;em&gt;, but that would make for a weird-looking sandwich. Ergo: sandwich
dilemma. (yes, you can ignore all of this.)&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;Option&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    Some(T),
&lt;&#x2F;span&gt;&lt;span&gt;    None,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; Option&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;J&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;: impl FnOnce(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; J) -&amp;gt; Option&amp;lt;J&amp;gt; { ... }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;my_option.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;| x.await)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will produce a compiler error: the closure &lt;code&gt;f&lt;&#x2F;code&gt; is not an async context, so
&lt;code&gt;.await&lt;&#x2F;code&gt; cannot be used within it. And we can&#x27;t just convert the closure to be
&lt;code&gt;async&lt;&#x2F;code&gt; either, since &lt;code&gt;fn map&lt;&#x2F;code&gt; doesn&#x27;t know how to call async functions. In
order to solve this issue, we could provide a new &lt;code&gt;async_map&lt;&#x2F;code&gt; method which
&lt;em&gt;does&lt;&#x2F;em&gt; provide an async closure. But we may want to repeat those for more
effects, and that would result in a combinatorial explosion of effects. Take for
example &quot;can fail&quot; and &quot;can be async&quot;:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;not async&lt;&#x2F;th&gt;&lt;th&gt;async&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;infallible&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn map&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn async_map&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;fallible&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn try_map&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn async_try_map&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;That&#x27;s a lot of API surface for just a single method, and &lt;strong&gt;that problem
multiplies across the entire API surface in the stdlib&lt;&#x2F;strong&gt;. We expect that once we
start applying &quot;keyword generics&quot; to traits, we will be able to solve the
sandwich problem. The type &lt;code&gt;f&lt;&#x2F;code&gt; would be marked generic over a set of effects,
and the compiler would choose the right variant during compilation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;affecting-all-effects&quot;&gt;Affecting all effects&lt;&#x2F;h2&gt;
&lt;p&gt;Both &lt;code&gt;const&lt;&#x2F;code&gt; and &lt;code&gt;async&lt;&#x2F;code&gt; share a very similar issue, and we expect that other
&quot;effects&quot; will face the same issue. &quot;fallibility&quot; is particularly on our mind here,
but it isn&#x27;t the only effect. In order for the language to feel consistent we
need consistent solutions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;faq&quot;&gt;FAQ&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;q-is-there-an-rfc-available-to-read&quot;&gt;Q: Is there an RFC available to read?&lt;&#x2F;h3&gt;
&lt;p&gt;Rust initiatives are intended for &lt;em&gt;exploration&lt;&#x2F;em&gt;. The announcement of the Keyword
Generics Initiative marks the &lt;em&gt;start&lt;&#x2F;em&gt; of the exploration process. Part of
exploring is not knowing what the outcomes will be. Right now we&#x27;re in the
&quot;pre-RFC&quot; phase of design. What we hope we&#x27;ll achieve is to enumerate the
full problem space, design space, find a balanced solution, and eventually
summarize that in the form of an RFC. Then after the RFC is accepted: implement
it on nightly, work out the kinks, and eventually move to stabilize.  But we may
at any point during this process conclude that this initiative is actually
infeasible and start ramping down.&lt;&#x2F;p&gt;
&lt;p&gt;But while we can&#x27;t make any &lt;em&gt;assurances&lt;&#x2F;em&gt; about the outcome of the initiative,
what we can share is that we&#x27;re pretty optimistic about the initiative overall.
We wouldn&#x27;t be investing the time we are on this if we didn&#x27;t think we&#x27;d be
actually be able to see it through to completion.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;q-will-this-make-the-language-more-complicated&quot;&gt;Q: Will this make the language more complicated?&lt;&#x2F;h3&gt;
&lt;p&gt;The goal of keyword generics is not to minimize the complexity of the Rust
programming language, but to &lt;em&gt;minimize the complexity of programming in Rust.&lt;&#x2F;em&gt;
These two might sound similar, but they&#x27;re not. Our reasoning here is that by
&lt;em&gt;adding&lt;&#x2F;em&gt; a feature, we will actually be able to significantly reduce the surface
area of the stdlib, crates.io libraries, and user code - leading to a more
streamlined user experience.&lt;&#x2F;p&gt;
&lt;p&gt;Choosing between sync or async code is a fundamental choice which needs to be
made. This is complexity which cannot be avoided, and which needs to exist
somewhere. Currently in Rust that complexity is thrust entirely on users of
Rust, making them responsible for choosing whether their code should support
async Rust or not. But other languages have made diferent choices. For example
Go doesn&#x27;t distinguish between &quot;sync&quot; and &quot;async&quot; code, and has a runtime which
is able to remove that distinction.&lt;&#x2F;p&gt;
&lt;p&gt;In today&#x27;s Rust application authors choose whether their application will be sync
or async, and even after the introduction of keyword generics we don&#x27;t really
expect that to change. All generics eventually need to have their types known,
and keyword generics are no different. What we&#x27;re targeting is the choice made
by &lt;em&gt;library&lt;&#x2F;em&gt; authors whether their library supports is sync or async. With
keyword generics library authors will be able to support both with the help of
the compiler, and leave it up to application authors to decide how they want to
compile their code.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;q-are-you-building-an-effect-system&quot;&gt;Q: Are you building an effect system?&lt;&#x2F;h3&gt;
&lt;p&gt;The short answer is: kind of, but not really. &quot;Effect systems&quot; or &quot;algebraic
effect systems&quot; generally have a lot of surface area. A common example of what
effects allow you to do is implement your own &lt;code&gt;try&#x2F;catch&lt;&#x2F;code&gt; mechanism. What we&#x27;re
working on is intentionally limited to built-in keywords only, and wouldn&#x27;t
allow you to implement anything like that at all.&lt;&#x2F;p&gt;
&lt;p&gt;What we do share with effect systems is that we&#x27;re integrating modifier keywords
more directly into the type system. Modifier keywords like &lt;code&gt;async&lt;&#x2F;code&gt; are often
referred to as &quot;effects&quot;, so being able to be conditional over them in
composable ways effectively gives us an &quot;effect algebra&quot;. But that&#x27;s very
different from &quot;generalized effect systems&quot; in other languages.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;q-are-you-looking-at-other-keywords-beyond-async-and-const&quot;&gt;Q: Are you looking at other keywords beyond &lt;code&gt;async&lt;&#x2F;code&gt; and &lt;code&gt;const&lt;&#x2F;code&gt;?&lt;&#x2F;h3&gt;
&lt;p&gt;For a while we were referring to the initiative as &quot;modifier generics&quot; or
&quot;modifier keyword generics&quot;, but it never really stuck. We&#x27;re only really
interested in keywords which modify how types work. Right now this is &lt;code&gt;const&lt;&#x2F;code&gt;
and &lt;code&gt;async&lt;&#x2F;code&gt; because that&#x27;s what&#x27;s most relevant for the const-generics WG and
async WG. But we&#x27;re designing the feature with other keywords in mind as well.&lt;&#x2F;p&gt;
&lt;p&gt;The one most at the top of our mind is a future keyword for fallibility. There
is talk about introducing &lt;code&gt;try fn() {}&lt;&#x2F;code&gt; or &lt;code&gt;fn () -&amp;gt; throws&lt;&#x2F;code&gt; syntax. This could
make it so methods such as &lt;code&gt;Iterator::filter&lt;&#x2F;code&gt; would be able to use &lt;code&gt;?&lt;&#x2F;code&gt; to break
out of the closure and short-circuit iteration.&lt;&#x2F;p&gt;
&lt;p&gt;Our main motiviation for this feature is that without it, it&#x27;s easy for Rust to
start to feel &lt;em&gt;disjointed&lt;&#x2F;em&gt;. We sometimes joke that Rust is actually 3-5
languages in a trenchcoat. Between const rust, fallible rust, async rust, unsafe
rust - it can be easy for common APIs to only be available in one variant of the
language, but not in others. We hope that with this feature we can start to
systematically close those gaps, leading to a more consistent Rust experience
for &lt;em&gt;all&lt;&#x2F;em&gt; Rust users.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;q-what-will-the-backwards-compatibility-story-be-like&quot;&gt;Q: What will the backwards compatibility story be like?&lt;&#x2F;h3&gt;
&lt;p&gt;Rust has pretty strict backwards-compatibility guarantees, and any feature we
implement needs to adhere to this. Luckily we have some wiggle room because of
the edition mechanism, but our goal is to shoot for maximal backwards compat. We
have some ideas of how we&#x27;re going to make this work though, and we&#x27;re
cautiously optimistic we might actually be able to pull this off.&lt;&#x2F;p&gt;
&lt;p&gt;But to be frank: this is by far one of the hardest aspects of this feature, and
we&#x27;re lucky that we&#x27;re not designing any of this just by ourselves, but have the
support of the language team as well.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;q-aren-t-implementations-sometimes-fundamentally-different&quot;&gt;Q: Aren&#x27;t implementations sometimes fundamentally different?&lt;&#x2F;h3&gt;
&lt;p&gt;Const Rust can&#x27;t make any assumptions about the host it runs on, so it can&#x27;t do
anything platform-specific. This includes using more efficient instructions of
system calls which are only available in one platform but not another. In order
to work around this, the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;intrinsics&#x2F;fn.const_eval_select.html&quot;&gt;&lt;code&gt;const_eval_select&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; intrinsic in the standard
library enables &lt;code&gt;const&lt;&#x2F;code&gt; code to detect whether it&#x27;s executing during CTFE or
runtime, and execute different code based on that.&lt;&#x2F;p&gt;
&lt;p&gt;For async we expect to be able to add a similar intrinsic, allowing library
authors to detect whether code is being compiled as sync or async, and do
something different based on that. This includes: using internal concurrency, or
switching to a different set of system calls. We&#x27;re not sure whether an
intrinsic is the right choice for this though; we may want to provide a more
ergonomic API for this instead. But because keyword generics is being designed
as a consistent feature, we expect that whatever we end up going with can be used
consistently by &lt;em&gt;all&lt;&#x2F;em&gt; modifier keywords.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve introduced the new keyword generics initiatve, explained why
it exists, and shown a brief example of what it might look like in the future.&lt;&#x2F;p&gt;
&lt;p&gt;The initiative is active on the Rust Zulip under
&lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.zulipchat.com&#x2F;#narrow&#x2F;stream&#x2F;328082-t-lang.2Fkeyword-generics&quot;&gt;&lt;code&gt;t-lang&#x2F;keyword-generics&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; - if this seems interesting to you, please
pop by!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Thanks to everyone who&#x27;s helped review this post, but in particular:
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fee1-dead&quot;&gt;fee1-dead&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;danielhenrymantilla&quot;&gt;Daniel Henry-Mantilla&lt;&#x2F;a&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rylev&quot;&gt;Ryan Levick&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Keywords I: Unsafe Syntax</title>
            <pubDate>Sat, 09 Jul 2022 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/unsafe-syntax/</link>
            <guid>https://blog.yoshuawuyts.com/unsafe-syntax/</guid>
            <description>&lt;p&gt;Last week &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;oli_obk&quot;&gt;Oli&lt;&#x2F;a&gt; and I were thinking through some examples involving modifiers and
&lt;code&gt;impl&lt;&#x2F;code&gt; blocks. Namely: would it be possible or even useful to declare something
like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; all methods in this block are `const`.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const impl &lt;&#x2F;span&gt;&lt;span&gt;MyStruct {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {}
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We thought this looked alright. But something we realized is that if we allowed
this for &lt;code&gt;const&lt;&#x2F;code&gt;, we&#x27;d likely want to allow this for all modifier keywords too,
including &lt;code&gt;unsafe&lt;&#x2F;code&gt;. And that unfortunately causes some issues. So this post is a
brief look at what those issues are, what plans exist to improve it, and how we
might even be able to do things better?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Note: The purpose of this post is mostly to share thoughts. I don&#x27;t speak for
Oli here, and I definitely don&#x27;t speak for any Rust team. Don&#x27;t take think of
this as a serious proposal, but instead think of it as notes which may come in
useful at a later time.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;two-meanings-of-unsafe&quot;&gt;Two meanings of unsafe&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;keyword.unsafe.html&quot;&gt;&lt;code&gt;unsafe&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; in Rust is actually two keywords in a trenchcoat. Depending on where
you use it, it&#x27;ll mean something different:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;On definition: &lt;code&gt;unsafe fn&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;unsafe trait&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;On usage: &lt;code&gt;unsafe {}&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;unsafe impl&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Each provides the following contract:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;On definition: there are additional invariants which the compiler cannot
check, so the programmer must check those by hand instead.&lt;&#x2F;li&gt;
&lt;li&gt;On usage: I&#x27;m manually checking invariants here which the compiler cannot
check for me.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Together these form a pair - not unlike &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt;. With the slight
difference that defining an &lt;code&gt;unsafe&lt;&#x2F;code&gt; block in a function body does not come with
the additional restriction that the function itself must also be marked as
&lt;code&gt;unsafe&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; using `.await` requires you wrap it in an `async` context, which propagates
&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; to the next caller:
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span&gt;().await;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; however using `unsafe` doesn&amp;#39;t require you wrap it in an `unsafe` context;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `fn foo` doesn&amp;#39;t also need to be `unsafe fn foo` here:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span&gt;() };
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And this makes sense: pretty much all of Rust builds on some foundation of
&lt;code&gt;unsafe&lt;&#x2F;code&gt;. So if &lt;code&gt;unsafe&lt;&#x2F;code&gt; was transitive much the same way &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; is,
then virtually every function would need to be marked &lt;code&gt;unsafe&lt;&#x2F;code&gt; - which would defeat the point of using &lt;code&gt;unsafe&lt;&#x2F;code&gt; as a sign post for where we&#x27;re manually checking invariants.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bringing-it-back-to-traits&quot;&gt;Bringing it back to traits&lt;&#x2F;h2&gt;
&lt;p&gt;So okay, that&#x27;s all well and good. But I mentioned we got onto this because we were
exploring the idea of allow keyword modifiers on entire blocks. Which is a
useful thing to have if, idk, you&#x27;re in the process of marking the majority of
the stdlib as &lt;code&gt;const&lt;&#x2F;code&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#constifying&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. If you&#x27;re able to declare things in a more
general way it makes things, uh, flow a bit more.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;constifying&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;In practice very few APIs cannot ever be called from &lt;code&gt;const fn&lt;&#x2F;code&gt; functions. Those are: all APIs which need to have knowledge of the host system (OS, filesystem, network devices, etc.) or have access to statics. I think that&#x27;s like, less than 10% of the total API surface in the stdlib; meaning the vast majority may eventually be constified. Not even to being about adding other types of effects (&lt;em&gt;cough&lt;&#x2F;em&gt; async &lt;em&gt;cough&lt;&#x2F;em&gt;) to the stdlib as well.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;But here&#x27;s where it gets odd. Take the following code:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;MyStruct;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe impl &lt;&#x2F;span&gt;&lt;span&gt;Send &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;MyStruct {}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This says: &quot;we promise the implementation of &lt;code&gt;Send&lt;&#x2F;code&gt; here is safe&quot;. But if we
adapt our &lt;code&gt;const impl&lt;&#x2F;code&gt; example from earlier to be &lt;code&gt;unsafe&lt;&#x2F;code&gt; impl instead we get
this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The intended meaning here is:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; &amp;quot;all methods in this block are `unsafe` to call&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe impl &lt;&#x2F;span&gt;&lt;span&gt;Foo {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {}
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This has the exact opposite meaning of our earlier &lt;code&gt;unsafe impl&lt;&#x2F;code&gt;! Doing this
means we&#x27;d have a semantic difference between inherent impls &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#inherent&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; and
trait impls. Which is a suuuuuper subtle distinction, and one which is almost guaranteed to trip people up!&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;inherent&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;This is jargon for: &quot;A regular impl block on a type&quot;. So not the
trait impl block.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;do-we-have-options&quot;&gt;Do we have options?&lt;&#x2F;h2&gt;
&lt;p&gt;There&#x27;s some things we might be able to do here. First option:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Do nothing!&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Yes, we could definitely choose to not care about this and move on. But that&#x27;s
an intellectual dead end, and I don&#x27;t like those. I&#x27;m choosing to care about
this instead. At least enough to write about it and think about it and think things through a bit more.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Color within the lines!&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;So what if we choose to restrict ourselves to making only additive changes here.
No breaking changes allowed. Well, we could yield that &lt;code&gt;unsafe impl&lt;&#x2F;code&gt; has the
meaning it has, and we can&#x27;t change that.  So maybe we could for example change
where we put the keyword to have different meanings. What if we
could make it something like this instead:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;MyStruct;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `unsafe impl` - this impl has been checked
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe impl &lt;&#x2F;span&gt;&lt;span&gt;Send &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;MyStruct {}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `impl unsafe` - the methods here need to be checked when used
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;unsafe MyStruct {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {}
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We could make it so &lt;code&gt;unsafe impl&lt;&#x2F;code&gt; means: &quot;this impl has been checked&quot;. And &lt;code&gt;impl unsafe&lt;&#x2F;code&gt; means: &quot;this implementation needs to be checked. That&#x27;s still subtle,
but at least it would no longer be identical. Adapting it to &lt;code&gt;const&lt;&#x2F;code&gt; would then
be:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `const impl` would be disallowed; that&amp;#39;s for `unsafe` only.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;const MyStruct {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {}
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is workable, but imo not ideal. When I say things out loud I definitely say
it&#x27;s a &quot;const impl&quot; or &quot;async impl&quot;. But we&#x27;d be writing it the other way
around.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;okay-so-what-if-we-start-coloring-outside-the-lines&quot;&gt;Okay, so what if we start coloring outside the lines?&lt;&#x2F;h2&gt;
&lt;p&gt;What if we actually took a step back and asked ourselves: &quot;if we
could start from scratch, what would we change about &lt;code&gt;unsafe&lt;&#x2F;code&gt;?&quot; Well, for
starters, I think &lt;a href=&quot;https:&#x2F;&#x2F;gankra.github.io&#x2F;blah&#x2F;tower-of-weakenings&#x2F;&quot;&gt;our memory
model&lt;&#x2F;a&gt; is looking pretty
good! So we wouldn&#x27;t want to bother too much there, and focus more on the
syntax.&lt;&#x2F;p&gt;
&lt;p&gt;Today having an &lt;code&gt;unsafe fn&lt;&#x2F;code&gt; implies the function body to be an
&lt;code&gt;unsafe {}&lt;&#x2F;code&gt; block. &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;blob&#x2F;master&#x2F;text&#x2F;2585-unsafe-block-in-unsafe-fn.md&quot;&gt;RFC
2585 (2020)&lt;&#x2F;a&gt;
was merged to break that assumption; presumably over the course of a few
editions (though afaict no decisions have been made on the exact process). But
that would move us one step closer to differentiating between the two meanings
of &lt;code&gt;unsafe&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;But what if we deprecated &lt;code&gt;unsafe&lt;&#x2F;code&gt; entirely instead? &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;pull&#x2F;117&quot;&gt;RFC
117 (2014)&lt;&#x2F;a&gt; suggested we do exactly this,
albeit pre-1.0. But given the &lt;em&gt;semantics&lt;&#x2F;em&gt; of &lt;code&gt;unsafe&lt;&#x2F;code&gt; wouldn&#x27;t change, but only
the syntax would, this is the type of change I believe we could run over an
edition bound.&lt;&#x2F;p&gt;
&lt;p&gt;Personally I like &lt;code&gt;checked&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;unchecked&lt;&#x2F;code&gt; to differentate between the two types
of &lt;code&gt;unsafe&lt;&#x2F;code&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#safe&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. It&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;?search=checked&quot;&gt;common
terminology&lt;&#x2F;a&gt; in the stdlib today
already, and it would solve the problem of &quot;what did you mean by &lt;code&gt;unsafe&lt;&#x2F;code&gt;&quot;
entirely. Our code examples could then be written like this:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;safe&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;I like &quot;checked&quot; more than I like &quot;safe&quot;. When I hear &lt;em&gt;safe&lt;&#x2F;em&gt; to me it
sounds like we&#x27;ve promised there are no bugs. And to quote Dijkstra: &lt;a href=&quot;http:&#x2F;&#x2F;homepages.cs.ncl.ac.uk&#x2F;brian.randell&#x2F;NATO&#x2F;nato1969.PDF&quot;&gt;Testing
shows the presence, not the absence of
bugs&lt;&#x2F;a&gt;. &lt;em&gt;At best&lt;&#x2F;em&gt;
we can guarantee we&#x27;ve checked for bugs. And its up to others to decide whether
they deem that safe enough.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;MyStruct;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; this implementation has been checked
&lt;&#x2F;span&gt;&lt;span&gt;checked &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Send &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;MyStruct {}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; these methods need to be checked
&lt;&#x2F;span&gt;&lt;span&gt;unchecked &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;MyStruct {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {}
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;See! No more ambiguity. And I think that&#x27;d be a huge step up from the status
quo! To spell out the other uses as well, here&#x27;s all existing uses of &lt;code&gt;unsafe&lt;&#x2F;code&gt;
translated to use &quot;check&quot; terminology:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `unsafe fn`
&lt;&#x2F;span&gt;&lt;span&gt;unchecked &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() {}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `unsafe trait`
&lt;&#x2F;span&gt;&lt;span&gt;unchecked &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;MyTrait {}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `unsafe impl`
&lt;&#x2F;span&gt;&lt;span&gt;checked &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Send &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;MyStruct {}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `unsafe {}`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    checked { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span&gt;() };
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;but-owo-there-s-more&quot;&gt;But owo there&#x27;s more!&lt;&#x2F;h2&gt;
&lt;p&gt;What? There&#x27;s more?&lt;&#x2F;p&gt;
&lt;p&gt;Yes! Because we now have a keyword pair, we can take a page out of the book of
other keyword pairs. Ergonomics matter in all parts of a language, but
especially so in places where the stakes are high. So what if we allowed&lt;&#x2F;p&gt;
&lt;p&gt;In RFC 2585 &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;nikomatsakis&quot;&gt;Niko&lt;&#x2F;a&gt; showed that many &lt;code&gt;unsafe&lt;&#x2F;code&gt; functions today are one-liners, and
making it so &lt;code&gt;unsafe fn&lt;&#x2F;code&gt; does not imply &lt;code&gt;unsafe {}&lt;&#x2F;code&gt; would yield the following
result:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(...) -&amp;gt; ... { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Code goes here
&lt;&#x2F;span&gt;&lt;span&gt;} }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, what if... we did away with &lt;code&gt;unsafe {}&lt;&#x2F;code&gt; blocks (or at least supplemented
them) and added a postfix operator operator? What if we could do this instead!:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;unchecked &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(...) -&amp;gt; ... { 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span&gt;().checked
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can probably debate exact words and syntax all day long. But the idea doesn&#x27;t
seem too bad, does it? Now granted, perhaps there are solid reasons to keep
blocks as well. But it&#x27;s common advice that &lt;code&gt;unsafe&lt;&#x2F;code&gt; blocks should be scoped as
tightly as possible. In today&#x27;s rust that often means we&#x27;re writing things like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(...) -&amp;gt; ... { 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span&gt;() }.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;baz&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And I think in comparison having a postfix notation would look a lot better:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;unchecked &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(...) -&amp;gt; ... { 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span&gt;().checked.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;baz&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;going-even-further&quot;&gt;Going even further?&lt;&#x2F;h2&gt;
&lt;p&gt;The core principle of Rust is that it can wrap unchecked internals into a
package which exposes checked semantics. This allows us to clearly scope which
parts of the program need to deal with manually checking invariants, and allows
the rest of the program to not have to care about any of that. Instead the
compiler helps us.&lt;&#x2F;p&gt;
&lt;p&gt;But not all checks are equal. I trust the stdlib devs to have carefully poured
over every single line of &lt;code&gt;unsafe&lt;&#x2F;code&gt; and done their best to ensure it&#x27;s correct.
At worst there might be a bug. But when I&#x27;m downloading code from third parties,
well, &lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;2022&#x2F;05&#x2F;10&#x2F;malicious-crate-rustdecimal.html&quot;&gt;we can be exposed to far more than bugs&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#safety&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;safety&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;I believe this is the first supply chain attack we&#x27;ve become aware
of. It does something bad during compilation. But a malicious crate might just
as well choose to do something bad during &lt;em&gt;runtime&lt;&#x2F;em&gt;. Supply chain attacks are
real, and as Rust grows, so will the frequency of attacks.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;code&gt;unsafe&lt;&#x2F;code&gt; is the building block that everything else is built on. Allowing all
code we download to do anything at all is not great. I mean: it&#x27;s &lt;em&gt;great&lt;&#x2F;em&gt;
insofar that we can wrap &lt;code&gt;openssl&lt;&#x2F;code&gt;, &lt;code&gt;libgit&lt;&#x2F;code&gt;, &lt;code&gt;winapi&lt;&#x2F;code&gt;, and more. But we tend to vet those packages, and make sure they&#x27;re from trusted sources. It&#x27;s not
great when that one random protocol parser I downloaded was actually turned out to be a piece of ransomware.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;mastodon.online&#x2F;@sunfish&quot;&gt;Sunfish&lt;&#x2F;a&gt; wrote a &lt;a href=&quot;https:&#x2F;&#x2F;blog.sunfishcode.online&#x2F;context-brainstorming&#x2F;&quot;&gt;thought
experiment&lt;&#x2F;a&gt; about what
it would take to create a sandbox backed by the Rust type system. And at least
we&#x27;d need to have a knob to turn off giving unrestricted access to &lt;code&gt;unsafe&lt;&#x2F;code&gt; to every function in every dependency we have.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;im_a_sweet_and_innocent_parser_uwu&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;reader&lt;&#x2F;span&gt;&lt;span&gt;: impl Read) -&amp;gt; ParsedTree {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;haha_no_im_not_lemme_break_into_ur_unpatched_kernel_real_quick&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    ParsedTree::new(reader)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The reason why I&#x27;m raising it here is because in a way this goes in the
&lt;em&gt;opposite&lt;&#x2F;em&gt; direction of RFC 2585. Instead of decoupling &lt;code&gt;unsafe fn&lt;&#x2F;code&gt; from &lt;code&gt;unsafe {}&lt;&#x2F;code&gt; it almost creates a tighter relationship between the two - but through
other means. In order to use &lt;code&gt;unsafe {}&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;checked {}&lt;&#x2F;code&gt; anywhere in a function,
the function signature would need to reflect that.&lt;&#x2F;p&gt;
&lt;p&gt;We wouldn&#x27;t want to make the &lt;code&gt;unsafe&lt;&#x2F;code&gt; keyword transitive so this would need to
behave differently than &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt;. But in order to &lt;em&gt;enable&lt;&#x2F;em&gt; &lt;code&gt;unsafe&lt;&#x2F;code&gt; to be
used, we&#x27;d want to share the &lt;em&gt;capability&lt;&#x2F;em&gt; to do so via the function signature.
The only types excluded from this mechanism would be the stdlib; since if you
trust the compiler you should also trust the stdlib.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `foo` needs maximum permissions (&amp;quot;ambient authority&amp;quot;) to
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; perform `unsafe`&#x2F;`checked` operations:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;with
&lt;&#x2F;span&gt;&lt;span&gt;    ambient_authority
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span&gt;().checked
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This would allow us to start flagging which functions depend on having the keys
to the castle, and which do not. Obviously that&#x27;s not the full story,
capabilities and especially &lt;em&gt;capability safety&lt;&#x2F;em&gt; are a pretty deep topic in and
of themselves. But because they would affect the function signature of &lt;code&gt;unsafe&lt;&#x2F;code&gt; types, it&#x27;s worth bringing up here.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Okay, so we kind of went hard on the changes we could plausibly want to make to
&lt;code&gt;unsafe&lt;&#x2F;code&gt; in the future. But I think that&#x27;s fine! - We at least figured a
plausible way out of the main drawback of RFC 2585 - though I guess a postfix
&lt;code&gt;unsafe&lt;&#x2F;code&gt; keyword could hold water even without the rename to
&lt;code&gt;checked&#x2F;unchecked&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;But equally importantly this would actually open the path to allowing
&lt;code&gt;const impl {}&lt;&#x2F;code&gt;, &lt;code&gt;async impl&lt;&#x2F;code&gt;, and possibly other effects in the future as well.
And that&#x27;s probably needed, because as we&#x27;re looking to make our typesystem more
powerful, we don&#x27;t want people to have to actually &lt;em&gt;type&lt;&#x2F;em&gt; more (get it) to make
use of it.&lt;&#x2F;p&gt;
&lt;p&gt;This initially was a &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;yoshuawuyts&#x2F;status&#x2F;1545190910253678592&quot;&gt;thread on
twitter&lt;&#x2F;a&gt;, but I
figured it might be worth giving it some permanence. I hope you enjoyed it; love
you.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Async Cancellation II: Time and Signals</title>
            <pubDate>Fri, 10 Jun 2022 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/async-cancellation-2/</link>
            <guid>https://blog.yoshuawuyts.com/async-cancellation-2/</guid>
            <description>&lt;p&gt;For the past few years I&#x27;ve been working on the &lt;code&gt;async-std&lt;&#x2F;code&gt; library, which
provides an async implementation of the APIs exposed by &lt;code&gt;std&lt;&#x2F;code&gt;. However, we also
added several new APIs related to things unique to async Rust: concurrency,
control over execution, and the interaction between the two.&lt;&#x2F;p&gt;
&lt;p&gt;These APIs were initially introduced in &lt;code&gt;async-std&lt;&#x2F;code&gt; as &quot;unstable&quot;, and have been
the main focus of my work to design since. On this blog there are numerous posts
related to for example:
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;futures-concurrency-3&#x2F;&quot;&gt;concurrency&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-cancellation-1&#x2F;&quot;&gt;cancellation&lt;&#x2F;a&gt;, and
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;postfix-spawn&#x2F;&quot;&gt;parallelism&lt;&#x2F;a&gt;. Today I want to
share a new experiment I&#x27;ve been working for time-based operations in async
Rust. I&#x27;ve designed it as a stand-alone crate for now, but I intend to PR its
addition to &lt;code&gt;async-std&lt;&#x2F;code&gt; in the near future.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;timer-basics&quot;&gt;Timer basics&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Relevant APIs here are:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-time&#x2F;latest&#x2F;futures_time&#x2F;task&#x2F;struct.Sleep.html&quot;&gt;&lt;code&gt;futures_time::task::Sleep&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-time&#x2F;latest&#x2F;futures_time&#x2F;stream&#x2F;struct.Interval.html&quot;&gt;&lt;code&gt;futures_time::stream::Interval&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In order to do anything with time you need to have timers. There are two basic
types of timers: a timer which fires once at a specific time, and a timer which
fires repeatedly after each interval &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#relation&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. In &lt;code&gt;futures-time&lt;&#x2F;code&gt; you can create both
these timers by concstructing these futures directly. But more interestingly: we
allow people to construct these futures by &lt;em&gt;convert an existing&lt;&#x2F;em&gt;
&lt;code&gt;time::Duration&lt;&#x2F;code&gt; or &lt;code&gt;time::Instant&lt;&#x2F;code&gt; directly into a timer through the
&lt;code&gt;IntoFuture&lt;&#x2F;code&gt; and &lt;code&gt;IntoStream&lt;&#x2F;code&gt; traits.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;relation&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;People would be right to point out that &lt;code&gt;Interval&lt;&#x2F;code&gt; can be
implemented in terms of &lt;code&gt;Sleep&lt;&#x2F;code&gt;. But even though that&#x27;s the case, APIs will have
to choose between &quot;do I fire once&quot; or &quot;do I fire repeatedly&quot;, and for that
reason it&#x27;s worth distinguishing between the two. Besides: &lt;code&gt;Interval&lt;&#x2F;code&gt; is so common
that we don&#x27;t want folks to have to implement it over and over, so we just provide it
as one of the two basic timer types.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Because both these traits are also implemented for all &lt;code&gt;T: Future&lt;&#x2F;code&gt; and
&lt;code&gt;T: Stream&lt;&#x2F;code&gt; respectively, time-based APIs can take &lt;code&gt;timer: impl IntoFuture&lt;&#x2F;code&gt; or
&lt;code&gt;instant: impl IntoStream&lt;&#x2F;code&gt; and pass either &lt;code&gt;Duration&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;Instant&lt;&#x2F;code&gt; directly, or
another future.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_timer::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_timer::{task, time::Duration};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;wait_until&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;timer&lt;&#x2F;span&gt;&lt;span&gt;: impl IntoFuture) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; timer = timer.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_future&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    timer.await;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;async_std&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Wait for a `Duration`.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;wait_until&lt;&#x2F;span&gt;&lt;span&gt;(Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Wait for a concrete future.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; deadline = task::sleep(Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;wait_until&lt;&#x2F;span&gt;&lt;span&gt;(deadline);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To simplify working with the orphan rules, we ended up defining our own variants
of &lt;code&gt;IntoFuture&lt;&#x2F;code&gt;, &lt;code&gt;IntoStream&lt;&#x2F;code&gt;, &lt;code&gt;Duration&lt;&#x2F;code&gt;, and &lt;code&gt;Instant&lt;&#x2F;code&gt;. When we move this to
&lt;code&gt;async-std&lt;&#x2F;code&gt; we can probably simplify some of it - but we&#x27;ll likely need to keep
our own definitions of &lt;code&gt;Duration&lt;&#x2F;code&gt; and &lt;code&gt;Instant&lt;&#x2F;code&gt; just for this to keep working.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cancelling-execution-at-a-distance&quot;&gt;Cancelling execution at a distance&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Relevant APIs here are:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-time&#x2F;latest&#x2F;futures_time&#x2F;future&#x2F;trait.FutureExt.html#method.timeout&quot;&gt;&lt;code&gt;futures_time::future::FutureExt::timeout&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-time&#x2F;latest&#x2F;futures_time&#x2F;stream&#x2F;trait.StreamExt.html#method.timeout&quot;&gt;&lt;code&gt;futures_time::stream::StreamExt::timeout&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;As I showed in the last section, thanks to the implementation of the &lt;code&gt;Into*&lt;&#x2F;code&gt;
traits functions can be agnostic over whether they take a &lt;code&gt;Duration&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;Instant&lt;&#x2F;code&gt;
instance, or whether they take a &lt;code&gt;Future&lt;&#x2F;code&gt;. For the last three years we&#x27;ve been
trying to figure out how we could integrate the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;stop-token&#x2F;latest&#x2F;stop_token&#x2F;&quot;&gt;&lt;code&gt;stop-token&lt;&#x2F;code&gt;
crate&lt;&#x2F;a&gt; into &lt;code&gt;async-std&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;For a deep-dive into how cancellation works in async Rust, you can read &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-cancellation-1&#x2F;&quot;&gt;the
last post in this series&lt;&#x2F;a&gt;.
But the short version is: futures can be cancelled between &lt;code&gt;.await&lt;&#x2F;code&gt; points just
by dropping the future. A timeout is nothing more than a &quot;race&quot; between a future
&lt;code&gt;F&lt;&#x2F;code&gt; and a timer future. If &lt;code&gt;F&lt;&#x2F;code&gt; completes first, you get an &lt;code&gt;Ok(value)&lt;&#x2F;code&gt;. And if the
timer completes first, you get an &lt;code&gt;Err(TimeoutError)&lt;&#x2F;code&gt;. That&#x27;s concepts composing
nicely with each other!&lt;&#x2F;p&gt;
&lt;p&gt;We tried various APIs for cancellation, but none really felt good. So I figured I
just needed to give it some time, and started looking at async temporal
operations. When I saw RxJS&#x27;s
&lt;a href=&quot;https:&#x2F;&#x2F;rxjs.dev&#x2F;api&#x2F;operators&#x2F;timeout&quot;&gt;&lt;code&gt;timeout&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;rxjs.dev&#x2F;api&#x2F;operators&#x2F;timeoutWith&quot;&gt;&lt;code&gt;timeoutWith&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; operators I realized
we might actually be able to combine both functionality through a single API. And instead of using a dedicated
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;stop-token&#x2F;0.2.0&#x2F;stop_token&#x2F;struct.StopSource.html&quot;&gt;&lt;code&gt;StopSource&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; &#x2F;
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;stop-token&#x2F;0.2.0&#x2F;stop_token&#x2F;struct.StopToken.html&quot;&gt;&lt;code&gt;StopToken&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
pair, we can instead reuse the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-channel&#x2F;latest&#x2F;async_channel&#x2F;&quot;&gt;&lt;code&gt;async-channel&lt;&#x2F;code&gt;
crate&lt;&#x2F;a&gt; to create a sender + receiver.
This is what it looks like when used together:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_lite::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_time::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_time::channel;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_time::time::Duration;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    async_io::block_on(async {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(send, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; recv) = channel::bounded::&amp;lt;()&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; create a new send&#x2F;receive pair
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; value = async { &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;meow&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; }
&lt;&#x2F;span&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;delay&lt;&#x2F;span&gt;&lt;span&gt;(Duration::from_millis(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;timeout&lt;&#x2F;span&gt;&lt;span&gt;(recv.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;()) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; time-out when the sender emits a message
&lt;&#x2F;span&gt;&lt;span&gt;            .await;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        assert_eq!(value.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(), &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;meow&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    })
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This example will always return &lt;em&gt;meow&lt;&#x2F;em&gt; because &lt;code&gt;send&lt;&#x2F;code&gt; is never dropped. But in a
concurrent example, a timeout could be triggered for all instances of &lt;code&gt;recv&lt;&#x2F;code&gt;
(which implements &lt;code&gt;Clone&lt;&#x2F;code&gt;) by dropping &lt;code&gt;send&lt;&#x2F;code&gt;. This is pretty nice because it
combines several individually useful components to create &quot;cancel at a distance
semantics&quot; which are usually reserved for dedicated APIs.&lt;&#x2F;p&gt;
&lt;p&gt;But there are still several rough edges in this API, which I think we may be
able to address:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;There are multiple imports from different crates required to get this to
work. Though this will likely be smoothed out somewhat by exposing it from
&lt;code&gt;async-std&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;When constructing a channel you have to declare a &lt;code&gt;mut recv&lt;&#x2F;code&gt; instead of
&lt;code&gt;recv&lt;&#x2F;code&gt;. This is because &lt;code&gt;recv.next()&lt;&#x2F;code&gt; expects &lt;code&gt;&amp;amp;mut self&lt;&#x2F;code&gt;. Implementing
&lt;code&gt;IntoFuture&lt;&#x2F;code&gt; for &lt;code&gt;async_channel::Receiver&lt;&#x2F;code&gt; would remove that requirement,
streamlining things somewhat.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;channel::bounded&lt;&#x2F;code&gt; needs to know what type it is, so it takes a &lt;code&gt;::&amp;lt;()&amp;gt;&lt;&#x2F;code&gt;
turbo-fish. Creating zero-sized channels for messaging is useful on its own,
so &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;36887&quot;&gt;once we&#x27;re able to &lt;&#x2F;a&gt; we
may want the constructor to default to a zero-sized type.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;If we migrate to &lt;code&gt;async-std&lt;&#x2F;code&gt; and have all these changes applied, usage might end
up looking somewhat like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::channel;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::time::Duration;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;async_std&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(send, recv) = channel::bounded(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; value = async { &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;meow&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; }
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;delay&lt;&#x2F;span&gt;&lt;span&gt;(Duration::from_millis(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;timeout&lt;&#x2F;span&gt;&lt;span&gt;(recv)
&lt;&#x2F;span&gt;&lt;span&gt;        .await;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    assert_eq!(value.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(), &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;meow&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;delaying-execution&quot;&gt;Delaying execution&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Relevant APIs here are:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-time&#x2F;latest&#x2F;futures_time&#x2F;future&#x2F;trait.FutureExt.html#method.delay&quot;&gt;&lt;code&gt;futures_time::future::FutureExt::delay&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-time&#x2F;latest&#x2F;futures_time&#x2F;stream&#x2F;trait.StreamExt.html#method.delay&quot;&gt;&lt;code&gt;futures_time::stream::StreamExt::delay&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-time&#x2F;latest&#x2F;futures_time&#x2F;future&#x2F;trait.FutureExt.html#method.park&quot;&gt;&lt;code&gt;futures_time::future::FutureExt::park&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-time&#x2F;latest&#x2F;futures_time&#x2F;stream&#x2F;trait.StreamExt.html#method.park&quot;&gt;&lt;code&gt;futures_time::stream::StreamExt::park&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Arbitrary cancellation of execution might be one of the most important features of async Rust,
but it&#x27;s not the only one. By gaining control over execution we also gain the
ability to delay, pause, and resume execution as well. Here&#x27;s an example of how
to delay an execution by a set time limit, or until a signal is sent:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_time::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_time::time::{Instant, Duration};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::future;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    async_io::block_on(async {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; value = future::ready(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;meow&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;delay&lt;&#x2F;span&gt;&lt;span&gt;(Duration::from_millis(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; delay resolving the future by 100ms
&lt;&#x2F;span&gt;&lt;span&gt;            .await;
&lt;&#x2F;span&gt;&lt;span&gt;        assert_eq!(value, Some(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;meow&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;));
&lt;&#x2F;span&gt;&lt;span&gt;    });
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I just authored the &lt;code&gt;park&lt;&#x2F;code&gt; methods for this post, but didn&#x27;t get around
to writing examples for them yet. &lt;code&gt;park&lt;&#x2F;code&gt; works similar to &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;thread&#x2F;fn.park.html&quot;&gt;&lt;code&gt;std::thread::park&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;,
but instead of only working on threads it works with &lt;em&gt;any&lt;&#x2F;em&gt; future or stream. You
call it by passing it a channel which can park or unpark the future, allowing
for convenient pausing and resuming of execution.&lt;&#x2F;p&gt;
&lt;p&gt;In &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;postfix-spawn&#x2F;#conclusion&quot;&gt;a previous post&lt;&#x2F;a&gt; I
mentioned that I suspect the right analogy for &quot;task&quot; is &lt;em&gt;&quot;parallelizable future&quot;&lt;&#x2F;em&gt;
rather than &lt;em&gt;&quot;async thread&quot;&lt;&#x2F;em&gt;, and showing that we can implement &lt;code&gt;park&lt;&#x2F;code&gt; for &lt;em&gt;all&lt;&#x2F;em&gt;
futures rather than only on &lt;code&gt;Task&lt;&#x2F;code&gt; is another indication that this new
model may in fact be the right one.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;throttling-execution&quot;&gt;Throttling execution&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Relevant APIs here are:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-time&#x2F;latest&#x2F;futures_time&#x2F;stream&#x2F;trait.StreamExt.html#method.buffer&quot;&gt;&lt;code&gt;futures_time::stream::StreamExt::buffer&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-time&#x2F;latest&#x2F;futures_time&#x2F;stream&#x2F;trait.StreamExt.html#method.debounce&quot;&gt;&lt;code&gt;futures_time::stream::StreamExt::debounce&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-time&#x2F;latest&#x2F;futures_time&#x2F;stream&#x2F;trait.StreamExt.html#method.sample&quot;&gt;&lt;code&gt;futures_time::stream::StreamExt::sample&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-time&#x2F;latest&#x2F;futures_time&#x2F;stream&#x2F;trait.StreamExt.html#method.throttle&quot;&gt;&lt;code&gt;futures_time::stream::StreamExt::throttle&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Generally data loss is considered a bad thing. But sometimes… data loss can be a
good thing? Take for example mouse presses: when something is clicked once, you
want to handle that. But if something is pressed 15 times in .3 seconds, perhaps
not so much. This is an example of &quot;external input&quot;, and since we cannot apply
backpressure to external conditions, the only method we have to reduce strain on
our system is to actively drop load.&lt;&#x2F;p&gt;
&lt;p&gt;In the crate we provide some versatile, basic methods to shed load based on
different circumstances. The &lt;code&gt;debounce&lt;&#x2F;code&gt; and &lt;code&gt;sample&lt;&#x2F;code&gt; methods get the last item
seen during a particular period. The &lt;code&gt;throttle&lt;&#x2F;code&gt; method will let through the first items received
during a particular period. And finally &lt;code&gt;buffer&lt;&#x2F;code&gt; groups data from a particular
time range into a vector, allowing operators to operate on chunks of data rather
than needing to decide on individual items.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_lite::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_time::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_time::time::{Instant, Duration};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_time::stream;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    async_io::block_on(async {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; counter = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;        stream::interval(Duration::from_millis(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; yield every 5ms
&lt;&#x2F;span&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;)                              &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; stop after 10 iterations
&lt;&#x2F;span&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;buffer&lt;&#x2F;span&gt;&lt;span&gt;(Duration::from_millis(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;))     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; create 20ms windows
&lt;&#x2F;span&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;for_each&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;| counter += buf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;())  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; sum all items
&lt;&#x2F;span&gt;&lt;span&gt;            .await;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        assert_eq!(counter, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    })
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;And that concludes the whirlwind-tour of the
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-time&#x2F;&quot;&gt;&lt;code&gt;futures-time&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate. I&#x27;m pretty happy with the
resulting APIs. For the longest time we were struggling to create APIs which
could operate on &lt;code&gt;{Duration, Instant, impl Future}&lt;&#x2F;code&gt;, and this usually resulted in
needing to declare three different APIs for each piece of functionality. The
insight that we could implement &lt;code&gt;IntoFuture&lt;&#x2F;code&gt; for &lt;code&gt;Instant&lt;&#x2F;code&gt; and &lt;code&gt;Duration&lt;&#x2F;code&gt; closed
that gap:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;recv&lt;&#x2F;span&gt;&lt;span&gt;: Receiver&amp;lt;()&amp;gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;                                                                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Notice how we&amp;#39;re using the same API:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; db = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;start_db&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;timeout&lt;&#x2F;span&gt;&lt;span&gt;(Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;)).await; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Timeout based on a duration
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; server = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;start_server&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;timeout&lt;&#x2F;span&gt;&lt;span&gt;(recv.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;()).await;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Timeout based on a signal
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;One of the things I&#x27;m least sure about though is what it feels like to convert a
&lt;code&gt;Duration&lt;&#x2F;code&gt; to a &lt;code&gt;Future&lt;&#x2F;code&gt; outside a trait bound. Admittedly this feels somewhat
awkward to me:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_time::time::Duration;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_time::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;).await; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; await a duration of 2 secs?
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I&#x27;m not sure. It might be the verb-noun thing, but it feels a bit weird. But
remembering an API Sean McArthur proposed years ago, we might be able to
streamline this a bit using conversion traits&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#playground&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;playground&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Note that &lt;code&gt;IntoDuration&lt;&#x2F;code&gt; does not yet exist, but here&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=stable&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=4ff4bd83b91a29be4c53b804be4fe3b5&quot;&gt;a playground link&lt;&#x2F;a&gt; to what that might look like.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_time::time::Duration;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_time::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;into_duration::IntoDuration;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;secs&lt;&#x2F;span&gt;&lt;span&gt;().await; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; wait for 2 secs.
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This reads a bit more fluent than what we might be used from most Rust APIs, but
I don&#x27;t think that&#x27;s a bad thing. I think it just takes some getting used to.
And it actually works quite nicely in other places too:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::channel;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::time::Duration;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;async_std&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; value = async { &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;meow&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; }
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;delay&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;millis&lt;&#x2F;span&gt;&lt;span&gt;())     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; &amp;lt;- using this API
&lt;&#x2F;span&gt;&lt;span&gt;        .await;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    assert_eq!(value.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(), &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;meow&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And thinking further ahead: if we get &lt;code&gt;async IntoIterator&lt;&#x2F;code&gt; + async iteration
syntax, having it implemented for &lt;code&gt;Duration&lt;&#x2F;code&gt; could allow us to write this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; start = Instant::now();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; await now in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;secs&lt;&#x2F;span&gt;&lt;span&gt;() {          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; loop every 1 second
&lt;&#x2F;span&gt;&lt;span&gt;    dbg!(now.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;duration_since&lt;&#x2F;span&gt;&lt;span&gt;(start)); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; print elapsed time
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Either way, there are some fun options available here. Implementing &lt;code&gt;IntoFuture&lt;&#x2F;code&gt;
&#x2F; &lt;code&gt;async IntoIterator&lt;&#x2F;code&gt; for &lt;code&gt;Duration&lt;&#x2F;code&gt; is one of the things I&#x27;m still least sure
about - but I wonder how much of it is just a matter of getting used to
something novel that&#x27;s now suddenly possible. I really don&#x27;t know.&lt;&#x2F;p&gt;
&lt;p&gt;That said though; I&#x27;m really happy with the way the library has turned out. And
I hope with some feedback and iteration it&#x27;ll be good enough to include into
&lt;code&gt;async-std&lt;&#x2F;code&gt;, and eventually also help us inform whether and how we want to expose this
functionality from the stdlib.&lt;&#x2F;p&gt;
&lt;p&gt;There are a bunch of time-based APIs we haven&#x27;t covered. But we certainly have
covered the fundamentals. And in particular I&#x27;m happy that we&#x27;ve finally found a
promising API for remote cancellation &#x2F; pausing &#x2F; resumption of arbitrary
futures. This is one of the key features async Rust provides, and actually
providing APIs for them seems important.&lt;&#x2F;p&gt;
&lt;p&gt;Either way, that&#x27;s what I have for now. If you want to check out the repo, you
can find it here:
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yoshuawuyts&#x2F;futures-time&quot;&gt;&lt;code&gt;yoshuawuyts&#x2F;futures-time&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. If
you&#x27;d like to keep up with my thoughts in near-real-time you can follow me on
&lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;yoshuawuyts&quot;&gt;Twitter&lt;&#x2F;a&gt;. And if you think the work I&#x27;m doing
is useful and you&#x27;d like to send me a tip, you can &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sponsors&#x2F;yoshuawuyts&quot;&gt;sponsor me
here&lt;&#x2F;a&gt;. Thanks!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Postfix Spawn</title>
            <pubDate>Fri, 04 Mar 2022 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/postfix-spawn/</link>
            <guid>https://blog.yoshuawuyts.com/postfix-spawn/</guid>
            <description>&lt;p&gt;Using a free &lt;code&gt;spawn&lt;&#x2F;code&gt; function to create new tasks has been &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio&#x2F;0.1.2&#x2F;tokio&#x2F;&quot;&gt;a staple&lt;&#x2F;a&gt; in async
Rust for many years. When we introduced &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;latest&#x2F;async_std&#x2F;&quot;&gt;&lt;code&gt;async-std&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; in 2019 we took this
further by not only providing a &lt;code&gt;spawn&lt;&#x2F;code&gt; function, but fully emulating the
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;thread&#x2F;index.html&quot;&gt;&lt;code&gt;std::thread&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; family of APIs and returning. But just because something has been around for a
while doesn&#x27;t mean it&#x27;s a good idea. And we know we have issues. In this post I
want to cover some of those issues, and share an experiment I&#x27;ve been working on
which may help with this.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;structured-concurrency&quot;&gt;Structured Concurrency&lt;&#x2F;h2&gt;
&lt;p&gt;In my previous post I covered the idea of &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-cancellation-1&#x2F;#structured-concurrency&quot;&gt;structured concurrency&lt;&#x2F;a&gt;.
Though it&#x27;s worth expanding on this concept more  in a separate post
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#conc-post&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, here&#x27;s the definition we&#x27;ll be using for the sake of this post:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Child tasks should never outlive their parent tasks (this includes destructors).&lt;&#x2F;li&gt;
&lt;li&gt;If we cancel a parent task the child task should be cancelled too.&lt;&#x2F;li&gt;
&lt;li&gt;If a child task raises an error, the parent task should be able to catch it.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The benefit of this is that code like this will never have &lt;em&gt;dangling tasks&lt;&#x2F;em&gt;, and
will largely run in a predictable manner. This has all sorts of interesting
properties, such as graceful shutdown trivially falling out of this model - but
as I mentioned, that&#x27;s something for a different post. The takeaway should be that
&quot;structured concurrency&quot; is a desirable property for any concurrent code to have.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;conc-post&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;I&#x27;ve been meaning to for a while now, but alas. Time limits are a thing.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;dangling-by-default&quot;&gt;Dangling by default&lt;&#x2F;h2&gt;
&lt;p&gt;As we mentioned in the same post last time, by default most popular runtimes do
not behave in a manner which is compatible with structured concurrency. When a
&lt;code&gt;JoinHandle&lt;&#x2F;code&gt; is dropped it isn&#x27;t joined or cancelled, instead it&#x27;s
&lt;em&gt;detached&lt;&#x2F;em&gt; causing it to dangle.&lt;&#x2F;p&gt;
&lt;p&gt;This behavior matches that of &lt;code&gt;std::thread::JoinHandle&lt;&#x2F;code&gt; as well, but &lt;a href=&quot;https:&#x2F;&#x2F;matklad.github.io&#x2F;2019&#x2F;08&#x2F;23&#x2F;join-your-threads.html&quot;&gt;as Matklad
remarked years ago&lt;&#x2F;a&gt; that behavior in threads is not without issues. In hindsight &quot;join on
drop&quot; would have been a better default, but we can&#x27;t easily change the behavior
of &lt;code&gt;std::thread&lt;&#x2F;code&gt; anymore. What we &lt;em&gt;can&lt;&#x2F;em&gt; do is ensure that the behavior of asynchronous tasks
default to the right thing. After all: modeling tasks after threads was a
&lt;em&gt;choice&lt;&#x2F;em&gt;, we can just as easily make a different choice. &lt;code&gt;std::task&lt;&#x2F;code&gt; is also the
one API we already don&#x27;t expect to want to &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-overloading&#x2F;&quot;&gt;overload&lt;&#x2F;a&gt;, which means
we&#x27;re not as restricted in the API space as we are with other async stdlib APIs.&lt;&#x2F;p&gt;
&lt;p&gt;So if threads are not the right type to emulate the behavior of for tasks, what
might be? I suspect the answer is &lt;code&gt;Future&lt;&#x2F;code&gt;. The &lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rfcs&#x2F;2592-futures.html&quot;&gt;futures API RFC&lt;&#x2F;a&gt;
mentions that cancelling futures should be done by dropping them.
Which means that if our tasks were to emulate futures, we should have
&quot;cancel-on-drop&quot; semantics too - as opposed to &quot;join on drop&quot; semantics.&lt;&#x2F;p&gt;
&lt;p&gt;There already exists a runtime which implements this in the wild: &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;smol&quot;&gt;&lt;code&gt;smol&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which
is powered by the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-task&#x2F;latest&#x2F;async_task&#x2F;&quot;&gt;&lt;code&gt;async-task&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate. &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-cancellation-1&#x2F;#propagating-cancellation-for-tasks&quot;&gt;&quot;cancel-on-drop&quot; semantics&lt;&#x2F;a&gt; mean that
cancellation of an outer task will automatically propagate to inner tasks as
well. Making it structurally concurrent by default.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;async-let&quot;&gt;async let&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;&quot;What if the behavior of futures and tasks were closer to each other&quot;&lt;&#x2F;em&gt; has
been an intrusive thought for me lately. Creating futures in Rust is
easy, but spawning tasks is significantly harder. Why is that? It turns that the
people working on Swift were pondering something similar not too long ago, and
they&#x27;ve implemented a solution: &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;apple&#x2F;swift-evolution&#x2F;blob&#x2F;main&#x2F;proposals&#x2F;0317-async-let.md&quot;&gt;&lt;code&gt;async let&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Here&#x27;s a
basic example of &lt;code&gt;async let&lt;&#x2F;code&gt; in action:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;swift&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-swift &quot;&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; given: 
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;   func chopVegetables() async throws -&amp;gt; [Vegetables]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;   func marinateMeat() async -&amp;gt; Meat
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;   func preheatOven(temperature: Int) async -&amp;gt; Oven
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;func &lt;&#x2F;span&gt;&lt;span&gt;makeDinner() async throws -&amp;gt; Meal {
&lt;&#x2F;span&gt;&lt;span&gt;  async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; veggies = chopVegetables()
&lt;&#x2F;span&gt;&lt;span&gt;  async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; meat = marinateMeat()
&lt;&#x2F;span&gt;&lt;span&gt;  async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; oven = preheatOven(temperature: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;350&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; dish = Dish(ingredients: await [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;try&lt;&#x2F;span&gt;&lt;span&gt; veggies, meat])
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return try&lt;&#x2F;span&gt;&lt;span&gt; await oven.cook(dish, duration: .hours(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Each instance of &lt;code&gt;async let&lt;&#x2F;code&gt; creates a Swift type equivalent to our &lt;code&gt;Task&lt;&#x2F;code&gt; type in Rust.
And awaiting an array of them is akin to our &lt;code&gt;future::join&lt;&#x2F;code&gt; operations.
Swift provides a global runtime out of the box, and awaiting one of these tasks
schedules it on the runtime, and executes it in parallel. This is pretty neat,
and compared to their &lt;code&gt;TaskGroup&lt;&#x2F;code&gt; approach for concurrency,
it &lt;em&gt;significantly&lt;&#x2F;em&gt; reduces the amount of code needed for many uses &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#arrays&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;arrays&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;I didn&#x27;t realize Swift had a way to concurrently await arrays. It
seems we&#x27;ve independently &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-concurrency&#x2F;2.0.3&#x2F;futures_concurrency&#x2F;index.html#examples&quot;&gt;come up with similar
solutions&lt;&#x2F;a&gt;.
That&#x27;s probaly a good sign!&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;What stands out to me is how easy this makes it to introduce ad-hoc
parallelism into a codebase. The difference between parallel code and
non-parallel code is the addition of a few &lt;code&gt;async&lt;&#x2F;code&gt; keywords sprinkled in front of
existing &lt;code&gt;let&lt;&#x2F;code&gt; statements. The ease of this is really cool, and I think we can
learn something from that!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;postfix-spawn&quot;&gt;Postfix spawn&lt;&#x2F;h2&gt;
&lt;p&gt;Now what if we could do this in Rust? Well, not &lt;em&gt;literally&lt;&#x2F;em&gt; the same, but &lt;em&gt;functionally&lt;&#x2F;em&gt;?
What if we could make spawning tasks not much harder than creating futures?
That&#x27;d be nice right? - and I&#x27;m happy to share I&#x27;ve got something working as
part of the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tasky&quot;&gt;tasky crate&lt;&#x2F;a&gt;. Here&#x27;s an example of it in use:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;tasky::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = async { &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;nori is a horse&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; }.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;().await;
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(res, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;nori is a horse&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will convert an existing future to a task, schedule it on the &lt;code&gt;async-std&lt;&#x2F;code&gt;
runtime, and await the result. But that&#x27;s not all; when we call &lt;code&gt;spawn&lt;&#x2F;code&gt; it
doesn&#x27;t actually create a task, it creates &lt;a href=&quot;http:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-finalizers&#x2F;&quot;&gt;an async builder&lt;&#x2F;a&gt;
which can be used to configure the task further before it&#x27;s started. For
example, we can use it to give our task a name before spawning it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = async { &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;nori is a loaf of bread&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; }
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;nori&amp;#39;s tuna stash&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;())
&lt;&#x2F;span&gt;&lt;span&gt;    .await;
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(res, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;nori is a loaf of bread&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The way the &quot;async builder&quot; pattern works is by using the nightly &lt;code&gt;IntoFuture&lt;&#x2F;code&gt;
trait. Just like &lt;code&gt;for item in iter&lt;&#x2F;code&gt; loops call &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; on &lt;code&gt;iter&lt;&#x2F;code&gt;. So will
&lt;code&gt;.await&lt;&#x2F;code&gt; call &lt;code&gt;IntoFuture&lt;&#x2F;code&gt; on whatever&#x27;s being awaited. In this case: the
&lt;code&gt;TaskBuilder&lt;&#x2F;code&gt; type. This enables us to create chaining builders that are
converted into futures when &lt;code&gt;.await&lt;&#x2F;code&gt;ed.&lt;&#x2F;p&gt;
&lt;p&gt;Now what would Swift&#x27;s earlier example look like if we translated it? For that
we&#x27;d need the &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;futures-concurrency-2&#x2F;&quot;&gt;&lt;code&gt;futures-concurrency&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; library too. Let&#x27;s take a look:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; given: 
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;   async fn chop_vegetables() throws -&amp;gt; io::Result&amp;lt;Vec&amp;lt;Vegetables&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;   async fn marinate_tofu() -&amp;gt; Tofu
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;   async fn preheat_oven(temperature: u16) -&amp;gt; Oven
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;tasky::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_concurrency::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::time::Duration;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::io;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;make_dinner&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; io::Result&amp;lt;Meal&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; veggies = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;chop_vegetables&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; meat = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;marinate_tofu&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; oven = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;preheat_oven&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;350&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; dish = Dish(&amp;amp;[veggies, meat].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_join&lt;&#x2F;span&gt;&lt;span&gt;().await?);
&lt;&#x2F;span&gt;&lt;span&gt;    oven.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;cook&lt;&#x2F;span&gt;&lt;span&gt;(dish, Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;60 &lt;&#x2F;span&gt;&lt;span&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;60 &lt;&#x2F;span&gt;&lt;span&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;)).await?
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are still a few warts; but this gets us &lt;em&gt;real&lt;&#x2F;em&gt; close to having semantics
as smooth as Swift&#x27;s. The most awkward
pieces of the example are that we don&#x27;t have &lt;code&gt;Duration::from_hours&lt;&#x2F;code&gt;, and the
array requires a &lt;code&gt;try_join&lt;&#x2F;code&gt; method instead of implementing &lt;code&gt;IntoFuture&lt;&#x2F;code&gt;. But
other than that: it&#x27;s quite close!&lt;&#x2F;p&gt;
&lt;p&gt;Converting the Swift example is nice to show that we can achieve parity with Swift,
but it doesn&#x27;t show how how much nicer postfix spawn is over the existing free
functions. For that, let&#x27;s take a look at what it looks like to spawn a longer
chain of futures on a task:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; free-function, inline variant
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; body = task::spawn(
&lt;&#x2F;span&gt;&lt;span&gt;    surf::get(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;https:&#x2F;&#x2F;foo.bar&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;header&lt;&#x2F;span&gt;&lt;span&gt;(some_header)
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;header&lt;&#x2F;span&gt;&lt;span&gt;(other_header)
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;body_json&lt;&#x2F;span&gt;&lt;span&gt;(data)
&lt;&#x2F;span&gt;&lt;span&gt;        .recv_json::&amp;lt;MyResponse&amp;gt;()
&lt;&#x2F;span&gt;&lt;span&gt;).await;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; free-function, variable variant
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; req = surf::get(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;https:&#x2F;&#x2F;foo.bar&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;header&lt;&#x2F;span&gt;&lt;span&gt;(some_header)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;header&lt;&#x2F;span&gt;&lt;span&gt;(other_header)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;body_json&lt;&#x2F;span&gt;&lt;span&gt;(data)
&lt;&#x2F;span&gt;&lt;span&gt;    .recv_json::&amp;lt;MyResponse&amp;gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; body = task::spawn(req).await;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; postfix method
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; body = surf::get(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;https:&#x2F;&#x2F;foo.bar&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;header&lt;&#x2F;span&gt;&lt;span&gt;(some_header)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;header&lt;&#x2F;span&gt;&lt;span&gt;(other_header)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;body_json&lt;&#x2F;span&gt;&lt;span&gt;(data)
&lt;&#x2F;span&gt;&lt;span&gt;    .recv_json::&amp;lt;MyResponse&amp;gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .await;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What we&#x27;re not showing in this example are the extra imports free-functions will
always require. Having a postfix spawn function would always just work as part
of the &lt;code&gt;Future&lt;&#x2F;code&gt; trait &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#future-trait&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Having postfix syntax is not only easier to use, it also composes better
with existing async features such as &lt;code&gt;.await&lt;&#x2F;code&gt; and &lt;code&gt;IntoFuture&lt;&#x2F;code&gt;. And removing
minor speedbumps for common operations is a part of API design that should not
be underestimated.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;future-trait&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;The working group is working on providing shared &lt;code&gt;spawn&lt;&#x2F;code&gt;
and &lt;code&gt;Task&lt;&#x2F;code&gt; abstractions from the stdlib. This is very much an API we could provide.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;design-considerations&quot;&gt;Design Considerations&lt;&#x2F;h2&gt;
&lt;p&gt;The implementation of &lt;code&gt;tasky&lt;&#x2F;code&gt;&#x27;s postfix &lt;code&gt;Future::spawn&lt;&#x2F;code&gt; methods are not yet as
polished as I&#x27;d like them to be. I knocked them out in about an hour last
Friday, and I&#x27;m out with COVID right now so I don&#x27;t see myself trying to polish
them anytime soon. Though I do think it might be useful to note what would be
done differently if I had the chance though. So let&#x27;s take a look at the
definition:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mod &lt;&#x2F;span&gt;&lt;span&gt;sealed {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Sealed trait to determine what type of bulider we got.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Kind {}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A local builder.
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Debug)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Local;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;sealed::Kind &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Local {}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A nonlocal builder.
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Debug)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;NonLocal;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;sealed::Kind &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;NonLocal {}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Task builder that configures the settings of a new task.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Builder&amp;lt;Fut: Future, K: sealed::Kind&amp;gt; { ... }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;Fut&amp;gt; IntoFuture &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Builder&amp;lt;Fut, NonLocal&amp;gt; { ... }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;Fut&amp;gt; IntoFuture &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Builder&amp;lt;Fut, Local&amp;gt; { ... }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;FutureExt: Future + Sized {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Spawn a task on a thread pool
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Builder&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;, NonLocal&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;: Send,
&lt;&#x2F;span&gt;&lt;span&gt;    {
&lt;&#x2F;span&gt;&lt;span&gt;        Builder {
&lt;&#x2F;span&gt;&lt;span&gt;            kind: PhantomData,
&lt;&#x2F;span&gt;&lt;span&gt;            future: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            builder: async_std::task::Builder::new(),
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Spawn a task on the same thread.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;spawn_local&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Builder&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;, Local&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        Builder {
&lt;&#x2F;span&gt;&lt;span&gt;            kind: PhantomData,
&lt;&#x2F;span&gt;&lt;span&gt;            future: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            builder: async_std::task::Builder::new(),
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We provide two methods on &lt;code&gt;Future&lt;&#x2F;code&gt;: &lt;code&gt;spawn&lt;&#x2F;code&gt; and &lt;code&gt;spawn_local&lt;&#x2F;code&gt;. One spawns &lt;code&gt;Send&lt;&#x2F;code&gt;
futures, the other one &lt;code&gt;!Send&lt;&#x2F;code&gt; futures &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#spawning-modes&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. The builder needs to
know what &quot;mode&quot; it&#x27;s in to spawn the right future using &lt;code&gt;IntoFuture&lt;&#x2F;code&gt;, so to do
that we thread through a generic param which dictates the spawning mode.&lt;&#x2F;p&gt;
&lt;p&gt;The way we currently do this is not ideal. &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;state-machines&#x2F;&quot;&gt;Enum variants aren&#x27;t types&lt;&#x2F;a&gt; yet, so
the best alternative we have is to emulate this using traits and manually
written types. Though I think, ideally, we&#x27;d be able to differentiate based on a
&lt;a href=&quot;https:&#x2F;&#x2F;tmandry.gitlab.io&#x2F;blog&#x2F;posts&#x2F;2021-12-21-context-capabilities&#x2F;&quot;&gt;context&lt;&#x2F;a&gt; so that we can be generic over the backend. We don&#x27;t have a notion yet
of what runtime APIs would look like in the stdlib, so perhaps surfacing this
as two different traits would actually work well.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;spawning-modes&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;These are not the only spawning modes possible; I should
write a post about a third mode (&lt;code&gt;Send&lt;&#x2F;code&gt; once, future will not move threads after
that) at some point. For now, check this out:
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;raftario&#x2F;async-into-future&quot;&gt;raftario&#x2F;async-into-future&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;The other thing this API hasn&#x27;t covered is the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;latest&#x2F;async_std&#x2F;task&#x2F;fn.spawn_blocking.html&quot;&gt;&lt;code&gt;spawn_blocking&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; API. This
convers synchronous operations to futures, backed by a thread pool. We &lt;em&gt;could&lt;&#x2F;em&gt;
have a postfix variant of this as well, but I&#x27;m not sure whether it&#x27;s a good
idea. In theory we could have a &lt;code&gt;.spawn&lt;&#x2F;code&gt; method for any type &lt;code&gt;T: !Future&lt;&#x2F;code&gt; using
some sort of trait. But I&#x27;m not sure how much value that would provide over a
free function. Personally I&#x27;m a bit wary of &lt;code&gt;spawn_blocking&lt;&#x2F;code&gt;, and think if we we
were to expose it from the stdlib, a free function would probably suffice.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;async-std&lt;&#x2F;code&gt; first proposed the model of: &quot;What if tasks are async threads&quot;. &lt;code&gt;smol&lt;&#x2F;code&gt; moved away from this by providing &quot;cancel-on-drop&quot; semantics.
In this post we showed some of the benefits gained by moving further away from
that model, and closer to: &quot;What if tasks are parallelizable futures?&quot;&lt;&#x2F;p&gt;
&lt;p&gt;In the future I&#x27;d very much like to explore whether we could move
even closer to the &quot;tasks-as-futures&quot; model. Right now the &lt;code&gt;tasky&lt;&#x2F;code&gt;
crate allows people to break structured concurrency guarantees by calling
&lt;code&gt;JoinHandle::detach&lt;&#x2F;code&gt; or &lt;code&gt;mem::forget(handle)&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;tasky::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{} } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; runs forever on a thread
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_future&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;detach&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What if we made it so tasks aren&#x27;t spawned on executors until &lt;code&gt;.await&lt;&#x2F;code&gt;ed, just
like futures? What if we did away with &lt;code&gt;detach&lt;&#x2F;code&gt; entirely? We can&#x27;t guarantee that
all runtimes behave this way, since people can implement their own. But for the
stdlib, would that make sense? This would still use &quot;cancel on drop semantics&quot;
since &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-cancellation-1&#x2F;&quot;&gt;&lt;code&gt;.await&lt;&#x2F;code&gt; points mark cancellation sites&lt;&#x2F;a&gt;. But we&#x27;d
also gain &quot;tasks aren&#x27;t started until &lt;code&gt;.await&lt;&#x2F;code&gt;ed&quot;, just like futures. Just how
much do we value having structured concurrency? Just what exactly does eager
execution of tasks provide us right now?&lt;&#x2F;p&gt;
&lt;p&gt;Structured concurrency increases safety in concurrent programs,
and I think it&#x27;s exploring in closer detail what it provides, and what we need
to do to achieve it. But until then: I hope you enjoyed this post! I wrote this because
indexing a bunch of the Swift proposals, learned about
&lt;code&gt;async let&lt;&#x2F;code&gt;, and got excited. And I hope you&#x27;re excited it now too!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Safe Pin Projections Through View Types</title>
            <pubDate>Fri, 04 Mar 2022 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/safe-pin-projections-through-view-types/</link>
            <guid>https://blog.yoshuawuyts.com/safe-pin-projections-through-view-types/</guid>
            <description>&lt;p&gt;&quot;Pinning&quot; is one of the harder concepts to wrap your head around when writing
async Rust. The idea is that we can mark something as: &quot;This won&#x27;t change memory
addresses from this point forward&quot;. This allows self-referential pointers to
work, which are needed for async borrowing over await points. Though that&#x27;s what
it&#x27;s useful for. In practice, how we use it is (generally) through one of three
techniques:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;stack pinning&lt;&#x2F;strong&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#stack&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;: this puts an object on the stack and ensures it
doesn&#x27;t move.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;heap pinning&lt;&#x2F;strong&gt;: using &lt;code&gt;Box::pin&lt;&#x2F;code&gt; to pin a type on the heap to ensure it
doesn&#x27;t move. This is often used as an alternative to stack pinning.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;pin projections&lt;&#x2F;strong&gt;: convert from coarse: &quot;This whole type is pinned&quot; to more
fine-grained: &quot;Actually only these fields on the type need to be pinned&quot;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;stack&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Annoyingly that&#x27;s inaccurate. We can have a future which we later box.
That means we pin on the &quot;stack&quot; only relative to the function, even if the
future itself may later live on the heap. &quot;inline&quot; vs &quot;out of bounds&quot; pinning
may be more accurate. Though if you look at what a &quot;stack&quot; and &quot;heap&quot; are, you
quickly find out those are made-up too. It&#x27;s all stuff living somewhere, maybe.
I find &quot;stack-pinning&quot; useful way to explain &quot;pinned inside the function body&quot;,
so let&#x27;s just go with that for now, alright?&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;“stack pinning” is the less common of the two operations, but we’re on a path to
adding first-class support to it via the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;pin-utils&#x2F;latest&#x2F;pin_utils&#x2F;&quot;&gt;&lt;code&gt;core::pin::pin!&lt;&#x2F;code&gt;
macro&lt;&#x2F;a&gt;. For “pin projection” we
don’t have a path towards inclusion yet, and we’re left relying on ecosystem
solutions such as the
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;pin-project&#x2F;latest&#x2F;pin_project&#x2F;&quot;&gt;&lt;code&gt;pin-project&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
crate&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#pin-project&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; (see footnote for praise).&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;pin-project&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;code&gt;pin-project&lt;&#x2F;code&gt; is an excellent piece of engineering; I want there
to be zero doubt about that. It&#x27;s what makes the futures ecosystem possible, and
has made it so that people (like myself) can &lt;em&gt;safely&lt;&#x2F;em&gt; author futures by hand
without risking undefined behavior. While this post seeks to explore ways in
which we might move past requiring the need to use &lt;code&gt;pin-project&lt;&#x2F;code&gt;, it&#x27;s not
because of issues with the crate. It&#x27;s because I think there might be additional
value in lifting this to the language level in a way that a crate cannot capture
(simply by nature of being a crate).&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;The status quo is not bad at all, but it’d be a shame if this is where we
stopped. Pinning is useful for so much more than just futures, and perhaps by
making it more accessible people could experiment with it more. In this post I
want to share the beginnings of an idea I have for how we might be able to add
pin projections as a first-class language feature to Rust.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-are-pin-projections&quot;&gt;What are pin projections?&lt;&#x2F;h2&gt;
&lt;p&gt;As we mentioned: pin projections convert from coarse “this whole type is
pinned” to more fine-grained: “Actually only these fields on the type need to be
pinned”.&lt;&#x2F;p&gt;
&lt;p&gt;There’s &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nightly&#x2F;std&#x2F;pin&#x2F;index.html#pinning-is-not-structural-for-field&quot;&gt;a thorough explainer about this on the &lt;code&gt;std::pin&lt;&#x2F;code&gt; docs in the
stdlib&lt;&#x2F;a&gt;.
But sometimes it’s better to show rather than tell. So let’s write a quick
example using the &lt;code&gt;pin-project&lt;&#x2F;code&gt; crate. Let’s create a &lt;code&gt;sleep&lt;&#x2F;code&gt; future which uses
&lt;em&gt;some&lt;&#x2F;em&gt; internal timer (work with me here &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#work-with-me&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;), and guarantees that it panics if it’s
polled again after it’s completed:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;work-with-me&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Those familiar enough with runtime implementations might
recognize this API as &lt;code&gt;async-io&lt;&#x2F;code&gt;&#x27;s &lt;code&gt;Timer&lt;&#x2F;code&gt; API. This type is &lt;code&gt;Unpin&lt;&#x2F;code&gt;, so if
we were actually using that here we didn&#x27;t need to perform pin projections for
things to work. But let&#x27;s pretend that our timer here &lt;em&gt;does&lt;&#x2F;em&gt; need to be pinned
so we can write an example.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Our main API which creates a future which wakes up after &amp;lt;dur&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;sleep&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;dur&lt;&#x2F;span&gt;&lt;span&gt;: Duration) -&amp;gt; Sleep {
&lt;&#x2F;span&gt;&lt;span&gt;    Sleep {
&lt;&#x2F;span&gt;&lt;span&gt;        timer: Timer::after(dur),
&lt;&#x2F;span&gt;&lt;span&gt;        completed: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Our future struct. The `timer` implements `Future`,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; and is the type we want to keep fixed in memory.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; But the `completed` field doesn&amp;#39;t need to be pinned,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; so we don&amp;#39;t mark it with &amp;quot;pin&amp;quot;.
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;pin_project&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Sleep {
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;pin&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;timer&lt;&#x2F;span&gt;&lt;span&gt;: Timer,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;completed&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Future &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Sleep {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output = Instant;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        assert!(!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.completed, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;future polled after completing&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; This is where the pin projection happens. We go from a `Pin&amp;lt;&amp;amp;mut Self&amp;gt;`
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; to a new type which can be thought of as:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `{ timer: Pin&amp;lt;&amp;amp;mut Timer, completed: bool }`
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; this = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;project&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; this.timer.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(cx) {
&lt;&#x2F;span&gt;&lt;span&gt;            Poll::Ready(instant) =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;                *this.completed = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;                Poll::Ready(instant.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;())
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;            Poll::Pending =&amp;gt; Poll::Pending,
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you haven’t seen any manual futures code before, that can be a lot to take
in. It’s a goal of the Rust Async WG to make it so people need to write as
little &lt;code&gt;Pin&lt;&#x2F;code&gt; code as possible to use async Rust. So if this overwhelming to you
&#x2F; you’re unsure what’s going on. Please don’t feel pressured you need to learn
this.&lt;&#x2F;p&gt;
&lt;p&gt;But for folks who are curious: the interesting part here is the call to
&lt;code&gt;self.project()&lt;&#x2F;code&gt;. This method is provided by the &lt;code&gt;pin-project&lt;&#x2F;code&gt; crate, and allows
us to convert from &lt;code&gt;Pin&amp;lt;&amp;amp;mut Self&amp;gt;&lt;&#x2F;code&gt; to a generated type where only certain
fields are pinned. I like to visualize it for myself like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; before projecting
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; Sleep &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt; timer: Timer, completed: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt; }&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; after projecting
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; Sleep { timer: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; Timer&amp;gt;, completed: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span&gt;}&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Both provide the guarantee that types which need to be pinned in fact &lt;em&gt;are&lt;&#x2F;em&gt;
pinned. But the “after projecting” example does so on a per-field basis, rather
than locking the whole thing in-place. And if the whole struct is locked in
place, it means we can’t mutate fields on it. Which in turn means we could never
mark &lt;code&gt;completed&lt;&#x2F;code&gt; as &lt;code&gt;true&lt;&#x2F;code&gt;. So we &lt;em&gt;have&lt;&#x2F;em&gt; to project to write stateful futures.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;view-types&quot;&gt;View Types&lt;&#x2F;h2&gt;
&lt;p&gt;In their post &lt;a href=&quot;http:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2021&#x2F;11&#x2F;05&#x2F;view-types&#x2F;&quot;&gt;“view types for
Rust”&lt;&#x2F;a&gt; Niko
talks about a new language construct called “view types” which can create a
finer-grained interface for borrowing values. The whole post is worth a read,
but to recap the example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; This is the code we start with
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;WonkaShipmentManifest {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;bars&lt;&#x2F;span&gt;&lt;span&gt;: Vec&amp;lt;ChocolateBar&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;golden_tickets&lt;&#x2F;span&gt;&lt;span&gt;: Vec&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;WonkaShipmentManifest {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;should_insert_ticket&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;index&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.golden_tickets.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;contains&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;index)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;WonkaShipmentManifest {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;prepare_shipment&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Vec&amp;lt;WrappedChocolateBar&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; result = vec![];
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(bar, i) in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.bars.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;zip&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..) {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; opt_ticket = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;should_insert_ticket&lt;&#x2F;span&gt;&lt;span&gt;(i) {
&lt;&#x2F;span&gt;&lt;span&gt;                Some(GoldenTicket::new())
&lt;&#x2F;span&gt;&lt;span&gt;            } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;                None
&lt;&#x2F;span&gt;&lt;span&gt;            };
&lt;&#x2F;span&gt;&lt;span&gt;            result.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(bar.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_wrapped&lt;&#x2F;span&gt;&lt;span&gt;(opt_ticket));
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;        result
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And it yields this error:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;error[E0382]: borrow of partially moved value: `self`
&lt;&#x2F;span&gt;&lt;span&gt;   --&amp;gt; src&#x2F;lib.rs:16:33
&lt;&#x2F;span&gt;&lt;span&gt;    |
&lt;&#x2F;span&gt;&lt;span&gt;15  |         for (bar, i) in self.bars.into_iter().zip(0..) {
&lt;&#x2F;span&gt;&lt;span&gt;    |                                   ----------- `self.bars` partially moved due to this method call
&lt;&#x2F;span&gt;&lt;span&gt;16  |             let opt_ticket = if self.should_insert_ticket(i) {
&lt;&#x2F;span&gt;&lt;span&gt;    |                                 ^^^^ value borrowed here after partial move
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However if we change the definition of &lt;code&gt;should_insert_ticket&lt;&#x2F;code&gt; to be more
fine-grained, we can tell the compiler that our borrows do not in fact overlap,
which makes the borrow checker happy.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;WonkaChocolateFactory {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;should_insert_ticket&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;{ golden_tickets } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;index&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;                          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ^ this is the &amp;quot;view type&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.golden_tickets.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;contains&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;index)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To me the core insight of “view types” is that by encoding more details in type
signatures, the compiler is able to make better decisions about what’s allowed
or not. Who’d have guessed?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;view-types-for-pin-projection&quot;&gt;View types for pin projection&lt;&#x2F;h2&gt;
&lt;p&gt;So far we’ve looked at “pin projection” and “view types” individually. But what
happens if we put them together? Could we express pin projections &lt;em&gt;using&lt;&#x2F;em&gt; view
types? I think we might! “view types” as proposed by Niko are a way to teach the
compiler about lifetimes in finer detail. I think we could apply the same logic
to use view types to teach the compiler about pinning in finer detail too.&lt;&#x2F;p&gt;
&lt;p&gt;⚠ &lt;em&gt;So before we dive in I want to remind folks again that this is just an idea. I’m
not on the lang team. I am in not in any position to make decisions about this.
I also don&#x27;t consider myself an expert in pin semantics, so I might have
gotten things wrong. I am not saying that we should prioritize work on this.
I&#x27;m sharing thoughts here in the hopes of, well, progressing the language. And
sometimes putting half-baked ideas into writing can help others refine them into
something practical later on.&lt;&#x2F;em&gt; ⚠&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, let’s take our earlier example and try and fit pin projections on it
using view types. Taking it very literally we could imagine the signature of
&lt;code&gt;Future::poll&lt;&#x2F;code&gt; to be possible to express like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; base
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; { .. }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; using view types. `timer` is pinned.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt;{ timer, completed } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; { .. }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Okay okay, this is a super literal application of “what if view types would just
do the pin projection”. But bear with me, we’ll go over all details in a second.
For now let’s just assume this works, and slot it into the earlier example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;sleep&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;dur&lt;&#x2F;span&gt;&lt;span&gt;: Duration) -&amp;gt; Sleep { .. }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Sleep {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;timer&lt;&#x2F;span&gt;&lt;span&gt;: Timer,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;completed&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Future &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Sleep {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output = Instant;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt;{ timer, completed } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ^ we&amp;#39;re using the view type here
&lt;&#x2F;span&gt;&lt;span&gt;        assert!(!completed, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;future polled after completing&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; timer.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(cx) {
&lt;&#x2F;span&gt;&lt;span&gt;            Poll::Ready(instant) =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;                *completed = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;                Poll::Ready(instant.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;())
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;            Poll::Pending =&amp;gt; Poll::Pending,
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I think overall this gets close to the feel we want pin projections to have.
Instead of our base type we narrow it down into its parts. But it’s probably not
everything we want to do yet, and it certainly doesn’t cover all aspects of pin
projections yet.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ergonomics&quot;&gt;Ergonomics&lt;&#x2F;h2&gt;
&lt;p&gt;In my opinion the &lt;code&gt;Future::poll&lt;&#x2F;code&gt; signature above is rather noisy; the view type
might have helped simplify the function body and struct declration, but it&#x27;s
definitely not helped the function signature. And somewhat annoyingly: we don&#x27;t
have any more information than we started with. We can&#x27;t actually tell which
fields are pinned!&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt;{ timer, completed } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; {
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Perhaps the compiler can be clever enough to infer that all &lt;code&gt;!Unpin&lt;&#x2F;code&gt; types in a
view type should remain pinned when viewed. But even if it can, type signatures
are as much for humans as they are for the compiler. And this tells us very
little about what is pinned. Instead I think it’d be clearer if this type of
lowering required contextual &lt;code&gt;pin&lt;&#x2F;code&gt; annotations:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt;{ pin timer, completed } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; {
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we can tell that the &lt;code&gt;timer&lt;&#x2F;code&gt; is pinned, but &lt;code&gt;completed&lt;&#x2F;code&gt; is not. We finally
have all the detail we need, but the signature is even more overwhelming than it
was. I think it&#x27;s worth asking at this point whether there&#x27;s anything we could
remove. If we look at the projected type, we can see there are three parts to it which
tell us what &quot;self&quot; is supposed to look like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;   &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;{ pin timer, completed } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ^                             ^     ^
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; |                             |     This only exists if `self` is this type.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; |                             This is about a `self` param.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; We have a mutable view type with these fields.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are three parts here, which if we assume we can remove one, we can have
three different permutations:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; view type + self
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt;{ pin timer, completed } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                                       ^ no right-hand `Pin&amp;lt;&amp;amp;mut Self&amp;gt;`
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; view type + self
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt;{ pin timer, completed } pin &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                                       ^ `Pin&amp;lt;&amp;amp;mut Self&amp;gt;` replaced by `pin self`
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; view type + arbitrary Self-type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt;{ pin timer, completed }: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;                                  ^ no left-hand `self` type
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; self + arbitrary Self-type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ... no view type :(
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;None of these feel particularly great, but they do provide us with some insight.
&lt;code&gt;Pin&amp;lt;&amp;amp;mut Self&amp;gt; can be useful to know _when_ this implementation is available. &lt;&#x2F;code&gt;self` is actually never used since we immediately destructure, but it is useful
to know that this is a method and not a free-function. The view type is what
makes pin projections possible, so we want to keep that somehow.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m not sure which attributes make most sense to highlight. The original design
keeps all properties, but feels overwhelming. On reviewing this post, my
co-worker Eric suggested we try and take &quot;view types&quot; proposal, performing
destructuring like we do in patterns, dropping the left-hand variable
declaration entirely:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; self + arbitrary Self-type + view type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt; pin timer, completed }&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; self + pin Self-type + view type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: pin &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt; { pin timer, completed }, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; view type + self
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt; { pin timer, completed }, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; view type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt; { pin timer, completed }, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; {
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I think we&#x27;ll need to keep the &lt;code&gt;self&lt;&#x2F;code&gt; param to not create confusion with &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;sync&#x2F;struct.Arc.html&quot;&gt;&lt;code&gt;Self&lt;&#x2F;code&gt;
methods&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#self-method&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. But
it&#x27;s hard to say which option out of these would be the best. The second one is
probably the simplest. But the first one conveys more information. Luckily we
don&#x27;t need to make any decisions now, so we can just settle for having looked at
the space a little.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;self-method&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;I honestly don&#x27;t understand why this isn&#x27;t a concrete method on
&lt;code&gt;Arc&lt;&#x2F;code&gt;. Is this so we don&#x27;t accidentally hit the &lt;code&gt;Deref&lt;&#x2F;code&gt; implementation? Perhaps
a compiler limitation? I don&#x27;t really get it, heh.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;pin-projections-and-drop&quot;&gt;Pin projections and drop&lt;&#x2F;h2&gt;
&lt;p&gt;Something we haven’t covered yet is that when pin projecting there are &lt;code&gt;Drop&lt;&#x2F;code&gt;
requirements. Put bluntly, the signature of &lt;code&gt;std::drop::Drop&lt;&#x2F;code&gt; is &lt;em&gt;wrong&lt;&#x2F;em&gt;. If
we’d known about “pinning” before Rust 1.0 we likely would&#x27;ve designed the
&lt;code&gt;Drop&lt;&#x2F;code&gt; trait differently.&lt;&#x2F;p&gt;
&lt;p&gt;The reason why &lt;code&gt;Drop&lt;&#x2F;code&gt; and pinning conflict is because once something has been
pinned it should pinned forever after &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#unless-unpin&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. But &lt;code&gt;Drop&lt;&#x2F;code&gt; takes &lt;code&gt;&amp;amp;mut self&lt;&#x2F;code&gt;, &lt;em&gt;even if a value has previously been pinned&lt;&#x2F;em&gt;, violating this requirement.
And so when we implement &lt;code&gt;Drop&lt;&#x2F;code&gt; for our async types we have to make sure to
always &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;pin&#x2F;index.html#drop-implementation&quot;&gt;convert &lt;code&gt;&amp;amp;mut self&lt;&#x2F;code&gt; back to &lt;code&gt;self: Pin&amp;lt;&amp;amp;mut Self&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;unless-unpin&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;Unless it&#x27;s unpinned. But &quot;unpin&quot; is basically: &quot;I don&#x27;t care
if I&#x27;m pinned or not, just do whatever&quot;, so let&#x27;s pretend we&#x27;re not talking
about it here either.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Drop &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Type {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `new_unchecked` is okay because we know this value is never used
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; again after being dropped.
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;inner_drop&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Pin::new_unchecked(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)});
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;inner_drop&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;this&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; Type&amp;gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Actual drop code goes here.
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;pin-project&lt;&#x2F;code&gt; crate covers this case for us. It disallows implementing
&lt;code&gt;Drop&lt;&#x2F;code&gt; manually, and requires we implement
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;pin-project&#x2F;latest&#x2F;pin_project&#x2F;attr.pinned_drop.html&quot;&gt;&lt;code&gt;pin_project::PinnedDrop&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
instead, which has the right signature:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::pin::Pin;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;pin_project::{pin_project, pinned_drop};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;pin_project&lt;&#x2F;span&gt;&lt;span&gt;(PinnedDrop)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;PrintOnDrop {
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;pin&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;field&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;pinned_drop&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;PinnedDrop &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;PrintOnDrop {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Dropping: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.field);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; _x = PrintOnDrop { field: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;50 &lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we want to make pinning more accessible, then we cannot just skip over the
interactions with &lt;code&gt;Drop&lt;&#x2F;code&gt;. I&#x27;m not sure whether this allows us to trigger
soundness bugs using purely safe Rust - but I suspect the answer to that is
likely irrelevant. It&#x27;s really easy to get lost in technicalities that we lose
sight of the wider point: Pinning has too many gotchas to use without
&lt;code&gt;pin-project&lt;&#x2F;code&gt;. And it&#x27;s hard to tease apart to which degree the issues are with
pinning as a concept, or mistakes we&#x27;ve made in the past in the language.&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps &quot;mistakes&quot; sounds too harsh. After all, &lt;code&gt;Pin&lt;&#x2F;code&gt; was introduced after Rust
1.0, so how could we have gotten this right? And while that&#x27;s true, I think that
perspective is a bit of a dead-end. If the issues are with &lt;code&gt;Pin&lt;&#x2F;code&gt;, then logically
we&#x27;ll seek to fix &lt;code&gt;Pin&lt;&#x2F;code&gt;. And realizing we&#x27;re unable to fix &lt;code&gt;Pin&lt;&#x2F;code&gt;, we&#x27;ll
naturally seek to limit the usage of it. &lt;strong&gt;But rather than thinking about pin as
&quot;introducing issues into Rust&quot;, what if we instead think of pin as &quot;surfacing
issues we have in Rust&quot;.&lt;&#x2F;strong&gt; Pin is a fundamental type in Rust. Transformative
even. It&#x27;s worth pondering what we could do with it if it was better integrated
into the language.&lt;&#x2F;p&gt;
&lt;p&gt;Maybe we should bite the bullet and actually &lt;em&gt;fix&lt;&#x2F;em&gt; our &lt;code&gt;Drop&lt;&#x2F;code&gt; impl. The main
reason why this hasn&#x27;t been done is because it&#x27;s backwards incompatible
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#backwards-compat&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. But likely the most important reason after that is because
it would grossly complicate the ergonomics of implementing &lt;code&gt;Drop&lt;&#x2F;code&gt; for people.
Perhaps that calculation changes if the ergonomics or pinning were less bad.
Say we took one of the ergo examples and applied it to our earlier drop example:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;backwards-compat&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;As my colleague Eric pointed out, one way we could replace
&lt;code&gt;Drop&lt;&#x2F;code&gt; with a new trait in a backwards-compatible manner is through blanket
impls.
We could define &lt;code&gt;PinnedDrop&lt;&#x2F;code&gt;, and provide a blanket impl of &lt;code&gt;PinnedDrop&lt;&#x2F;code&gt; for &lt;code&gt;T: Drop + Unpin&lt;&#x2F;code&gt;. Then we change the compiler to desugar drops to a pin and a call
to &lt;code&gt;PinnedDrop::drop&lt;&#x2F;code&gt; instead. Though replacing &lt;code&gt;Drop&lt;&#x2F;code&gt; with something else (even
for something as important as soundness) might be tricky to coordinate and
communicate.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;PrintOnDrop {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;field&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Drop &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;PrintOnDrop {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; We&amp;#39;ve dropped `self: Pin&amp;lt;&amp;amp;mut Self&amp;gt;` from our signature
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; because we immediately destructure it into its parts
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; inside the type signature anyway.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: pin &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt; { pin field }) {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Dropping: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, field);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; _x = PrintOnDrop { field: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;50 &lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I don&#x27;t think this looks noticably worse than today&#x27;s drop trait. And hold onto
your tin-foil caps, I think this could possibly hint at another set of
optimizations we might be able to perform. What if for structs where all types
are &lt;code&gt;Unpin&lt;&#x2F;code&gt; we could create whole-sale projections. &lt;code&gt;u8&lt;&#x2F;code&gt; here doesn&#x27;t actually
need to be pinned, it&#x27;s just for show. So what if we actually were able to write
that:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;PrintOnDrop {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;field&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Drop &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;PrintOnDrop {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; This is a short-hand for a destructuring of `Pin&amp;lt;&amp;amp;mut Self&amp;gt;`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; where all fields are `Unpin`, requiring no pinning and thus
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; no destructuring.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Dropping: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.field);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; _x = PrintOnDrop { field: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;50 &lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;destructuring can be nice. That would allow us to write &lt;code&gt;&amp;amp;mut self&lt;&#x2F;code&gt; as sugar for
&lt;code&gt;self: Pin&amp;lt;&amp;amp;mut Self&amp;gt; where Self: Unpin&lt;&#x2F;code&gt;. Meaning: &lt;strong&gt;for all &lt;em&gt;sound&lt;&#x2F;em&gt;
implementations of &lt;code&gt;Drop&lt;&#x2F;code&gt; everything would continue working as they do today.&lt;&#x2F;strong&gt;
The only difference is that the trait declaration of &lt;code&gt;Drop&lt;&#x2F;code&gt; would change. And
we&#x27;d catch potential unsound invocations of &lt;code&gt;Drop&lt;&#x2F;code&gt;, requiring them to be sound
at the function signature level. This includes &lt;code&gt;pin-project&lt;&#x2F;code&gt;&#x27;s use as well, but
we&#x27;d likely be able to coordinate roll-out, deprecation, etc. in the crate.&lt;&#x2F;p&gt;
&lt;p&gt;This is not unlike how &lt;code&gt;&amp;amp;mut self&lt;&#x2F;code&gt; is syntactic sugar for &lt;code&gt;&amp;amp;mut self: &amp;amp;mut Self&lt;&#x2F;code&gt;
already. We could make it so that we can lower &lt;code&gt;Pin&amp;lt;&amp;amp;mut Self&amp;gt;&lt;&#x2F;code&gt; to &lt;code&gt;Self&lt;&#x2F;code&gt; if
it&#x27;s always safe to do so. Anyway. That&#x27;s probably enough speculation for this
section. To close it off, so far we haven&#x27;t yet figured out how to introduce
&lt;code&gt;async Drop&lt;&#x2F;code&gt; into the language. One option mentioned so far been to &lt;a href=&quot;https:&#x2F;&#x2F;without.boats&#x2F;blog&#x2F;poll-drop&#x2F;&quot;&gt;extend
&lt;code&gt;Drop&lt;&#x2F;code&gt; with &lt;code&gt;poll&lt;&#x2F;code&gt; methods&lt;&#x2F;a&gt;. However way
we go about this, we&#x27;ll have to be looking more closely at &lt;code&gt;Drop&lt;&#x2F;code&gt; and &lt;code&gt;Pin&lt;&#x2F;code&gt; soon
anyway.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;repr-packed&quot;&gt;#[repr(packed)]&lt;&#x2F;h2&gt;
&lt;p&gt;There are other considerations such as not being able to pin a &lt;code&gt;#[repr(packed)]&lt;&#x2F;code&gt;
type. And honestly: I’m not super sure how we can fix all of this. Maybe we
should raise &lt;code&gt;#[repr(packed)]&lt;&#x2F;code&gt; into the type-system and make &lt;code&gt;Pin&amp;lt;T&amp;gt; where T: !marker::Packed&lt;&#x2F;code&gt;. Or perhaps pin projections should magick their way into
knowing not to do this. I&#x27;m not sure. But this is something to figure out if we
want to remove the &lt;code&gt;unsafe {}&lt;&#x2F;code&gt; marker for pin projections.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;unpin&quot;&gt;Unpin&lt;&#x2F;h2&gt;
&lt;p&gt;So far we haven&#x27;t talked about &lt;code&gt;Unpin&lt;&#x2F;code&gt; at all. I mean, unless you&#x27;ve read the
footnotes. But I assume that&#x27;s nobody, so here&#x27;s a recap: &lt;code&gt;Unpin&lt;&#x2F;code&gt; means that a
type simply doesn&#x27;t care about &lt;code&gt;Pin&lt;&#x2F;code&gt; at all. Moving it around in memory won&#x27;t
cause it to spontaniously combust, so we can just move it in and out of &lt;code&gt;Pin&lt;&#x2F;code&gt;
wrappers whenever we like. This is true for most types ever created. Only types
which are self-referential (hold pointers to fields contained within itself) are
marked as &lt;code&gt;!Unpin&lt;&#x2F;code&gt;. Which is true for many futures created using &lt;code&gt;async {}&lt;&#x2F;code&gt;,
because that&#x27;s what borrows across &lt;code&gt;.await&lt;&#x2F;code&gt; points desugar into.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Unpin&lt;&#x2F;code&gt; is an auto-trait: meaning it&#x27;s implemented for a type if all the fields
of the type implement it. But unlike auto-trait such as &lt;code&gt;Send&lt;&#x2F;code&gt; and &lt;code&gt;Sync&lt;&#x2F;code&gt;, it&#x27;s
entirely &lt;em&gt;safe&lt;&#x2F;em&gt; to implement. And this causes some issues.&lt;&#x2F;p&gt;
&lt;p&gt;This means that even if our struct contains types which are &lt;code&gt;!Unpin&lt;&#x2F;code&gt;, we can
still manually implement &lt;code&gt;Unpin&lt;&#x2F;code&gt; on it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::marker::PhantomPinned;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::marker::Unpin;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `Foo` holds an `!Unpin` type, which makes
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `Foo: !Unpin`.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Foo {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;_marker&lt;&#x2F;span&gt;&lt;span&gt;: PhantomPinned
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Oh nevermind, we can just mark it as `Unpin` anyway.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Unpin &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Foo {}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I believe the reasoning is that since &quot;pin projections&quot; require &lt;code&gt;unsafe&lt;&#x2F;code&gt;,
upholding the validity of &lt;code&gt;Unpin&lt;&#x2F;code&gt; should just be done there.
But that&#x27;s an issue if we&#x27;re looking for ways to actually make pin projections
safe to perform. Upholding invariants shouldn&#x27;t be done at the projection site;
it needs to be done on declaration!&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;pin-project&lt;&#x2F;code&gt; crate works around this by disallowing safe implementations of
&lt;code&gt;Unpin&lt;&#x2F;code&gt; and instead introducing &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;pin-project&#x2F;latest&#x2F;pin_project&#x2F;trait.UnsafeUnpin.html&quot;&gt;their own &lt;code&gt;UnsafeUnpin&lt;&#x2F;code&gt;
trait&lt;&#x2F;a&gt;.
This flips the safety requirement back to the &lt;code&gt;Unpin&lt;&#x2F;code&gt; implementation, requiring
invariants are upheld by the implementer of the trait.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;pin_project::{pin_project, UnsafeUnpin};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;pin_project&lt;&#x2F;span&gt;&lt;span&gt;(UnsafeUnpin)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Struct&amp;lt;K, V&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;pin&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;field_1&lt;&#x2F;span&gt;&lt;span&gt;: K,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;field_2&lt;&#x2F;span&gt;&lt;span&gt;: V,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Implementing `Unpin` is unsafe here.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;K, V&amp;gt; UnsafeUnpin &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Struct&amp;lt;K, V&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where&lt;&#x2F;span&gt;&lt;span&gt; K: Unpin + Clone {}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Which means calling `struct.project()` later on can be safe.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In order for pin projections to be safe, manual implementations of &lt;code&gt;Unpin&lt;&#x2F;code&gt; need
to be &lt;code&gt;unsafe&lt;&#x2F;code&gt;. This is because someone needs to be responsible for correctly
implementing the invariants; and it either needs to be where we perform the
projection, or where we declare types as &lt;code&gt;Unpin&lt;&#x2F;code&gt;. &quot;both&quot; is annoying. &quot;neither&quot;
is impossible &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#impossible&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;impossible&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;We need to be able to label types as &lt;code&gt;Unpin&lt;&#x2F;code&gt; somehow. Even if
every type in the stdlib implements it, the stdlib itself is not magic. And in
the ecosystem too: core types require being able to be marked with it.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;It seems that if we want to make pin projections a first-class construct in
Rust, we&#x27;ll have to mark &lt;code&gt;Unpin&lt;&#x2F;code&gt; as &lt;code&gt;unsafe&lt;&#x2F;code&gt;. Annoyingly this would be a change
to the stdlib, and we don&#x27;t have a process like &quot;editions&quot; where we can flip a
switch on changes like these. At least not yet.&lt;&#x2F;p&gt;
&lt;p&gt;Making this happen wouldn&#x27;t be easy. And we&#x27;d need to assess whether the impact
justifies going down this path. But maybe it does. And maybe we should.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pin-keyword-in-other-places&quot;&gt;Pin keyword in other places?&lt;&#x2F;h2&gt;
&lt;p&gt;At the start of this post we mentioned that stack-pinning is gaining first-class
support in Rust via the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;pin-utils&#x2F;latest&#x2F;pin_utils&#x2F;&quot;&gt;&lt;code&gt;core::pin::pin!&lt;&#x2F;code&gt;
macro&lt;&#x2F;a&gt;. But later on in the post we
also discuss the possibility of improving pin projection semantics by
introducing a &lt;code&gt;pin&lt;&#x2F;code&gt; keyword in the view type. It&#x27;s worth asking: could a &lt;code&gt;pin&lt;&#x2F;code&gt;
keyword be useful in other places too?&lt;&#x2F;p&gt;
&lt;p&gt;I think, maybe? Even without view types, we could imagine all function
signatures which currently take &lt;code&gt;self: Pin&amp;lt;&amp;amp;mut Self&amp;gt;&lt;&#x2F;code&gt; could probably be
simplified to take &lt;code&gt;pin self&lt;&#x2F;code&gt; instead:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Before
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Future {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;            ^ Using an &amp;quot;arbitrary self type&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; After
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Future {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: pin &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;            ^ Replaced by a `pin` keyword.
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Additionally, for stack pinning we could imagine we could replace the use of
&lt;code&gt;core::pin::pin!&lt;&#x2F;code&gt; with pin-bindings:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Before
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;block_on&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fut&lt;&#x2F;span&gt;&lt;span&gt;: impl Future&amp;lt;Output = T&amp;gt;) -&amp;gt; T {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; fut = pin::pin!(fut);
&lt;&#x2F;span&gt;&lt;span&gt;    ...
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Using `let pin` bindings in the function body.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;block_on&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fut&lt;&#x2F;span&gt;&lt;span&gt;: impl Future&amp;lt;Output = T&amp;gt;) -&amp;gt; T {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; pin fut = fut;
&lt;&#x2F;span&gt;&lt;span&gt;    ...
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Using `pin` in the function signature.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;block_on&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt;(pin &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fut&lt;&#x2F;span&gt;&lt;span&gt;: impl Future&amp;lt;Output = T&amp;gt;) -&amp;gt; T {
&lt;&#x2F;span&gt;&lt;span&gt;    ...
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I don&#x27;t think this looks particularly out of place. It might be nice even.
But the real question to ask is: is this useful? We have so many things we
could be working on that we have to choose what to prioritize. Right now &quot;pin&quot;
is probably misunderstood and under-used because it doesn&#x27;t play well with the
language. But if we fixed those issues, would we see people use &lt;code&gt;pin&lt;&#x2F;code&gt; for more
things &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#self-referential&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;? It&#x27;s a bit of a chicken&#x2F;egg problem; though we do
need to have &lt;em&gt;some&lt;&#x2F;em&gt; an answer in order to justify spending time on this.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;self-referential&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;&#x2F;sup&gt;
&lt;p&gt;As we mentioned: &lt;code&gt;Pin&lt;&#x2F;code&gt; is what makes borrowing over
&lt;code&gt;.await&lt;&#x2F;code&gt; points work by allowing us to define self-referential structs. But
outside of &lt;code&gt;.await&lt;&#x2F;code&gt; we cannot yet define self-referential structs. If pinning is
required to make that work, maybe there&#x27;s reason to improve the ergonomics? I&#x27;m
genuinely unsure; but I think that&#x27;s the direction we should be asking questions
in.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post I’ve shown what pin projections are, what view types are, how the
two could be combined, ergonomics considerations, possible interactions with
&lt;code&gt;Drop&lt;&#x2F;code&gt;, and interactions with &lt;code&gt;Unpin&lt;&#x2F;code&gt;. In general it seems there are 3 questions
to answer?:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Can we use view types to create pin projections? What should that look like?&lt;&#x2F;li&gt;
&lt;li&gt;How can we fix the signature of &lt;code&gt;Drop&lt;&#x2F;code&gt;?&lt;&#x2F;li&gt;
&lt;li&gt;How can we lift &lt;code&gt;#[repr(Packed)]&lt;&#x2F;code&gt; into the type system so we can disallow it to be pinned?&lt;&#x2F;li&gt;
&lt;li&gt;If we want to make pin projections safe, can we mark &lt;code&gt;Unpin&lt;&#x2F;code&gt; as &lt;code&gt;unsafe&lt;&#x2F;code&gt;?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Have I missed anything? Are there any other parts to consider? I’m not sure. I
also want to point out that we don’t need a single unifying answer to solve all
of these questions. It may be that each item has a different solution; but once
we solve all of them we can start to realize safe pin projections at the lang
level. As I’ve mentioned a few times now, I’d be keen to hear from others.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, this is just some stuff I started thinking of after having read Niko’s
view types blog post midway through writing a bunch of futures by hand. I’m not
sure whether delving deeper into this idea is worth it at all right now. As I
mentioned pinning has &lt;em&gt;potential&lt;&#x2F;em&gt;, but we’re trying hard to make users interact
with it as little as possible. Kind of like how we have &lt;code&gt;unsafe&lt;&#x2F;code&gt;, but we don’t
really want people interacting with it much if we can help it, even if the
stakes are different.&lt;&#x2F;p&gt;
&lt;p&gt;From what I’ve heard the Linux kernel folks are making use of pinning for some
of the things they&#x27;re doing already. I&#x27;m not sure what they&#x27;re doing it for, but
it’d be &lt;em&gt;fascinating&lt;&#x2F;em&gt; to learn why. If people are thinking of improving the
ergonomics of &lt;code&gt;unsafe&lt;&#x2F;code&gt; to make it less hard to use. Perhaps it’d be worth to do
the same for pinning as well?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;ryan_levick&quot;&gt;Ryan Levick&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;theinedibleholk&quot;&gt;Eric Holk&lt;&#x2F;a&gt; for helping review and correct this
post prior to publishing. &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;nikomatsakis&quot;&gt;Niko Matsakis&lt;&#x2F;a&gt; for entertaining my delirious
ramblings about this on Zulip a few days ago. And &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;withoutboats&quot;&gt;Boats&lt;&#x2F;a&gt;, with who I&#x27;m pretty
sure I&#x27;ve discussed something like this before, even though time is a lie and
at this point I no longer remember how long ago that may have been.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>More Enum Types</title>
            <pubDate>Tue, 15 Feb 2022 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/more-enum-types/</link>
            <guid>https://blog.yoshuawuyts.com/more-enum-types/</guid>
            <description>&lt;p&gt;Yesterday I was talking with folks on Zulip about &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;futures-concurrency-3&#x2F;&quot;&gt;my last blog
post&lt;&#x2F;a&gt;, and
specifically about the potential ergonomic improvements “anonymous enums” could
provide. In my post we only really looked at anonymous enums as a potential
ergonomics improvement for &lt;code&gt;Stream::merge&lt;&#x2F;code&gt;. But in this post I instead want to
dig ever so slightly deeper and show how &lt;em&gt;symmetry&lt;&#x2F;em&gt; is missing in the Rust
language between struct and enum variants.&lt;&#x2F;p&gt;
&lt;p&gt;So I&#x27;m writing this post to dig into that some more. We&#x27;ll be keeping it brief,
focusing mostly on showing something which stood out to me. The intent is less
so for me to be making recommendations about the
direction the language should take, and mostly on walking you through my
observations. There are times when I spend months performing rigorous analysis
of things, and there’s times like these when I just want to share some thoughts.
This post also serves as practice for me to edit less and publish faster.&lt;&#x2F;p&gt;
&lt;p&gt;So with all that out of the way, let’s dig in by looking at structs first.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;structs&quot;&gt;Structs&lt;&#x2F;h2&gt;
&lt;p&gt;Structs are Rust’s most common data container. They come in three flavors: empty
(no fields), record (key-value), or tuple (indexed fields). All three roughly
work the same, and for the sake of simplicity we’ll only be looking at tuple
structs in this post. So let’s start defining one!&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;MyStruct(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That’s right, that’s a tuple struct. It has two fields, both of which must be
populated. And it has a bunch of derives, which allow us to perform common,
useful operations on it. Now let’s create one and return it from a function.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;MyStruct(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; named type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; MyStruct {
&lt;&#x2F;span&gt;&lt;span&gt;    MyStruct(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you’ve ever used a tuple-struct that should look pretty familiar, right? We
created an instance of the type, and returned it from the function. But you
might be noticing that this is actually quite a bit of boilerplate. IDEs can
help us with the derives. But they can’t help us work around defining the type,
the layout, and naming it. What if we didn’t actually care about the name? Say,
if this was just a helper function in our file? For cases where naming the
returned types isn’t useful, we can use tuples:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; anonymous type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This does almost the exact same thing as the code we had before, but it’s now
much shorter! Gone is the struct declaration. And gone are the derives. This
works because tuples have generic impls on them which say: “if all of my members
implement a trait, then so will I.” You can almost think of it as automatically
deriving traits, while named structs need to declare which traits they want to
derive.&lt;&#x2F;p&gt;
&lt;p&gt;Now finally, sometimes we don’t want to expose which type we return. Often
because we don’t want to provide any stability guarantees about the type we
return. We want to be able to say: “the type we return conforms to this
interface, but that’s all I’m telling you.” For example &lt;code&gt;-&amp;gt; impl Future&lt;&#x2F;code&gt; was
pretty common to author before we had &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; (in fact &lt;code&gt;async {}&lt;&#x2F;code&gt;
generates an &lt;code&gt;impl Future&lt;&#x2F;code&gt; type, also known as “anonymous future”). But we can
write this in our own code like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; type erased type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; impl Debug {
&lt;&#x2F;span&gt;&lt;span&gt;    MyStruct(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;All this tells us is: “the type we’re returning here implements &lt;code&gt;Debug&lt;&#x2F;code&gt;, and
that’s it”.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;enums&quot;&gt;Enums&lt;&#x2F;h3&gt;
&lt;p&gt;Now let’s take a look at enums. Much like structs, enums can carry values as
well (empty, record, tuple) - but instead of being AND (contain multiple
values), they give us XOR (contain an exclusive, single value) &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#record_enums&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.
Not sure how much sense this explainer makes, but please pretend it does. In an
enum, only one variant is active at any given time. So let’s define an enum
where we either have a &lt;code&gt;u32&lt;&#x2F;code&gt; or a &lt;code&gt;u16&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;record_enums&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Yes, &quot;record enums&quot; give us XOR and then AND. But those are
almost like a different kind of shorthand for having named record fields nested
in enums. If we have to go into those we&#x27;ll never finish this post. So let&#x27;s
not think about them too much for now.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;MyEnum {
&lt;&#x2F;span&gt;&lt;span&gt;    Left(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    Right(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The way we return an enum from a function is by constructing a variant. This is
often times done based on a condition. So let’s pretend we have a function which
is given a condition, and computes which enum to return:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;MyEnum {
&lt;&#x2F;span&gt;&lt;span&gt;    Left(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    Right(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; named type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cond&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; MyEnum {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; cond { MyEnum::Left(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;) } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{ MyEnum::Right(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;) }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will either return the number &lt;code&gt;100u32&lt;&#x2F;code&gt; or the number &lt;code&gt;12u16&lt;&#x2F;code&gt;. That makes sense right?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;anonymous-enums&quot;&gt;Anonymous enums&lt;&#x2F;h2&gt;
&lt;p&gt;Now what if we wanted to simplify this, say if we were writing a quick helper.
The boilerplate of defining an enum and derives might be distracting, and much
like a tuple we just want to send some data along. We might imagine that we
would want to write this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; named type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cond&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16 &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; made up syntax for u32 OR u16
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; cond { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100 &lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12 &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However, Rust doesn’t support this. Unlike “anonymous structs” (tuples), there
is no such thing as an “anonymous enum”. There’s an &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;issues&#x2F;294#issuecomment-761604444&quot;&gt;open issue about
it&lt;&#x2F;a&gt;, but I
don’t know anyone who’s working on it. And I don’t know of any crates which
provide implementations of this either.&lt;&#x2F;p&gt;
&lt;p&gt;Something which makes it difficult to prototype “anonymous enums” is that the
syntax comes in pairs: not only do we need to figure out how to define them in
function return positions, we need to think about how to use them as well. The
version I’ve seen which I like the most used type ascription when matching, but
that’s &lt;em&gt;hard&lt;&#x2F;em&gt; to implement, and has a bunch of other lang implications as well:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(cond) {
&lt;&#x2F;span&gt;&lt;span&gt;    n: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span&gt;=&amp;gt; {},
&lt;&#x2F;span&gt;&lt;span&gt;    n: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16 &lt;&#x2F;span&gt;&lt;span&gt;=&amp;gt; {}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Though if someone has ideas how to prototype this, it would be fun to see what people can come up with.&lt;&#x2F;p&gt;
&lt;p&gt;Probably the closest we can get to “anonymous enums” is by using the
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;either&#x2F;1.6.1&#x2F;either&#x2F;&quot;&gt;either&lt;&#x2F;a&gt; crate from the ecosystem. I
believe once upon a time this crate lived in the stdlib (pre 1.0), and it
provides us with a &lt;code&gt;Result&lt;&#x2F;code&gt;-like type which holds two generic params: one for
the left-hand variant, and one for the right-hand variant. Much like “anonymous
enums”, it allows us to bypass having to provide our own enum by having a
pre-made one.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;either::Either;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; named type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cond&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Either&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; cond { Either::Left(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;) } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{ Either::Right(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;) }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In the wild, types such as
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;latest&#x2F;futures&#x2F;future&#x2F;struct.Select.html#impl-Future&quot;&gt;&lt;code&gt;futures::future::Select&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
yield &lt;code&gt;Either&lt;&#x2F;code&gt; variants when wanting to return one of two types. This works
alright when joining two different futures, but when attempting to join more
than two, you’ll end up with nested &lt;code&gt;Join&amp;lt;Join&amp;lt;First, Second&amp;gt;, Third&amp;gt;&lt;&#x2F;code&gt;, etc
constructions which are not fun to work with.&lt;&#x2F;p&gt;
&lt;p&gt;In my opinion it would be better if &lt;code&gt;Future::select&lt;&#x2F;code&gt;&#x2F; &lt;code&gt;Future::race&lt;&#x2F;code&gt; would
return a single type &lt;code&gt;T&lt;&#x2F;code&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;futures-concurrency-2&#x2F;#how-to-expose-futures-concurrency&quot;&gt;allow &lt;code&gt;race&lt;&#x2F;code&gt; to operate over N futures
concurrently&lt;&#x2F;a&gt;,
and make enum construction an explicit step. That way if Rust ever gets
anonymous enums, the compiler could inference we’re passing different types,
which can be unified using an anonymous enum.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The compiler could infer the Future&amp;#39;s return type T
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; should be an anonymous enum, which we can subsequently
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; match over
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span&gt;(a, b, c).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;race&lt;&#x2F;span&gt;&lt;span&gt;().await {
&lt;&#x2F;span&gt;&lt;span&gt;    n: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span&gt;=&amp;gt; {},
&lt;&#x2F;span&gt;&lt;span&gt;    n: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16 &lt;&#x2F;span&gt;&lt;span&gt;=&amp;gt; {},
&lt;&#x2F;span&gt;&lt;span&gt;    n: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str &lt;&#x2F;span&gt;&lt;span&gt;=&amp;gt; {},
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In &lt;code&gt;async-std&lt;&#x2F;code&gt; the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;latest&#x2F;async_std&#x2F;future&#x2F;trait.Future.html#method.race&quot;&gt;&lt;code&gt;Future::race&lt;&#x2F;code&gt; method&lt;&#x2F;a&gt; already returns a single type &lt;code&gt;T&lt;&#x2F;code&gt;
instead of an &lt;code&gt;Either&lt;&#x2F;code&gt; type. And for &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-concurrency&#x2F;latest&#x2F;futures_concurrency&#x2F;&quot;&gt;&lt;code&gt;futures-concurrency&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; we’re likely going to
do the same &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#futfut&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, but instead of providing a &lt;code&gt;race&lt;&#x2F;code&gt; method from &lt;code&gt;Future&lt;&#x2F;code&gt;, provide a
&lt;code&gt;Race&lt;&#x2F;code&gt; trait directly from container types (though we’re likely going to rename
the traits before we merge them. Current contender: &lt;code&gt;first&#x2F;First&lt;&#x2F;code&gt; method&#x2F;trait).&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;futfut&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;The plan is to merge &lt;code&gt;futures-concurrency&lt;&#x2F;code&gt; back into &lt;code&gt;async-std&lt;&#x2F;code&gt; once
we figure out all the parts of it. But that&#x27;s been taking a minute, and will
likely take a bit longer. But it&#x27;s important we get this right, sooooo. Hence
the last 3 years of work.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;type-erased-enums&quot;&gt;Type-erased enums&lt;&#x2F;h2&gt;
&lt;p&gt;Now, taking things one level of abstraction further: what if we have N values,
but we only care about the shape of the values returned. We could imagine we
could write something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; type erased type (currently unsupported)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cond&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; impl Debug {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; cond { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16 &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Both of these implement &lt;code&gt;Debug&lt;&#x2F;code&gt;, and the syntax is valid this time around. So this should work right? Unfortunately not. We get &lt;a href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=stable&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=8b2c8888a303f7a32a7319f705abf4a4&quot;&gt;the following error&lt;&#x2F;a&gt; if we try this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;error[E0308]: `if` and `else` have incompatible types
&lt;&#x2F;span&gt;&lt;span&gt; --&amp;gt; src&#x2F;lib.rs:4:31
&lt;&#x2F;span&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;span&gt;4 |     if cond { 100u32 } else { 12u16 }
&lt;&#x2F;span&gt;&lt;span&gt;  |               ------          ^^^^^ expected `u32`, found `u16`
&lt;&#x2F;span&gt;&lt;span&gt;  |               |
&lt;&#x2F;span&gt;&lt;span&gt;  |               expected because of this
&lt;&#x2F;span&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;span&gt;help: you could change the return type to be a boxed trait object
&lt;&#x2F;span&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;span&gt;3 | fn foo(cond: bool) -&amp;gt; Box&amp;lt;dyn Debug&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;  |                       ~~~~~~~      +
&lt;&#x2F;span&gt;&lt;span&gt;help: if you change the return type to expect trait objects, box the returned expressions
&lt;&#x2F;span&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;span&gt;4 |     if cond { Box::new(100u32) } else { Box::new(12u16) }
&lt;&#x2F;span&gt;&lt;span&gt;  |               +++++++++      +          +++++++++     +
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Translating what the compiler is trying to tell us here: “You cannot use &lt;code&gt;impl Debug&lt;&#x2F;code&gt; here, please use &lt;code&gt;Box&amp;lt;dyn Debug&amp;gt;&lt;&#x2F;code&gt; instead”. But taking the compiler up on
their suggestion forces us to allocate the value on the heap instead of the
stack, and to go through a pointer vtable to find the right value to dispatch
to. But as we saw earlier: we could also just define an enum to get the same
effect. The suggestion made by the compiler here is sensible, but not &lt;em&gt;optimal&lt;&#x2F;em&gt;.
Though the compiler is not at fault, there’s definitely something missing here.
And I suspect if type-erased enums were supported by the language, the compiler
would never have to suggest how to work around this in the first place, thus
making the issue go away entirely.&lt;&#x2F;p&gt;
&lt;p&gt;Fortunately “type-erased enums” &lt;em&gt;do&lt;&#x2F;em&gt; have a crate in the ecosystem which shows
us what using this would feel like:
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;auto_enums&#x2F;latest&#x2F;auto_enums&#x2F;index.html&quot;&gt;auto_enums&lt;&#x2F;a&gt;. By adding
just a few annotations our code suddenly works:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;auto_enum&lt;&#x2F;span&gt;&lt;span&gt;(Debug)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cond&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; impl Debug {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; cond { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16 &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;auto_enums&lt;&#x2F;code&gt; uses a proc macro to generate an enum for each type in
the code. We have to tell it which traits the output type should implement, but
other than that it reads fairly naturally.&lt;&#x2F;p&gt;
&lt;p&gt;Looking at the code generate by the &lt;code&gt;auto_enums&lt;&#x2F;code&gt; crate, I suspect that this
should be fairly straight forward to implement in the compiler if we can get
lang approval for it. Which at first glance doesn’t seem like a big language
feature either. But I don’t know enough about this side of the language to
appropriately judge what gotchas might apply (const, FFI, etc. all need to be
considered). So I don’t know how difficult this might be in practice to see
through to completion. But I’d be interested to hear from any lang&#x2F;compiler
folks whether my intuition here is right?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;comparing-enums-and-structs&quot;&gt;Comparing enums and structs&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we’ve taken a look at both structs and enums, we can capture their capabilities in a table:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;Structs&lt;&#x2F;th&gt;&lt;th&gt;Enums&lt;&#x2F;th&gt;&lt;th&gt;Enums Fallback&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Named&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;struct Foo(.., ..)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;enum Foo { .., .. }&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Anonymous&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;(.., ..)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;❌&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;either&lt;&#x2F;code&gt; crate&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Type-Erased&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;impl Trait&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;❌&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;auto_enums&lt;&#x2F;code&gt; crate&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;As you can see, it&#x27;s much easier to quickly create a struct than it is to create
an enum. Fallbacks for quick enum creation exist in the ecosystem, but
Even if both structs and enums can both hold rich data, the bar to using structs
in Rust is lower than for enums. I would argue, significantly so.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;&#x2F;h2&gt;
&lt;p&gt;We’ve shown the differences between struct and enum definitions. And shown how
the lack of anonymous and type-erased enums is worked around today using crates
from the ecosystem.&lt;&#x2F;p&gt;
&lt;p&gt;My current thinking is that fixing this asymmetry would be beneficial for Rust
eventually. It’s a convenient piece of polish which could make daily driving
Rust nicer. But it’s nothing fundamental that needs to be addressed straight
away. So I don’t think it’s anything which requires being prioritized.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, I got thinking about this when chatting with folks about this earlier,
and figured I’d put my thinking into words. In part to share the idea, and in
part to learn how to publish things more quickly. If you liked this post, and
would like to see what I make for dinner, &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;yoshuawuyts&quot;&gt;follow me on
Twitter&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;appendix-a-examples&quot;&gt;Appendix A: Examples&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;structs-1&quot;&gt;Structs&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;MyStruct(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; named type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; MyStruct {
&lt;&#x2F;span&gt;&lt;span&gt;    MyStruct(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; anonymous type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; type erased type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; impl Debug {
&lt;&#x2F;span&gt;&lt;span&gt;    MyStruct(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;enums-1&quot;&gt;Enums&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;MyEnum {
&lt;&#x2F;span&gt;&lt;span&gt;    Left(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    Right(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; named type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cond&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; MyEnum {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; cond { MyEnum::Left(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;) } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{ MyEnum::Right(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;) }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; anonymous type (currently unsupported)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cond&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; cond { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16 &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; type erased type (currently unsupported)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cond&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; impl Debug {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; cond { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16 &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;appendix-b-tables&quot;&gt;Appendix B: Tables&lt;&#x2F;h2&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;Structs&lt;&#x2F;th&gt;&lt;th&gt;Enums&lt;&#x2F;th&gt;&lt;th&gt;Enums Fallback&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Named&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;struct Foo(.., ..)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;enum Foo { .., .. }&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Anonymous&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;(.., ..)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;❌&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;either&lt;&#x2F;code&gt; crate&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Type-Erased&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;impl Trait&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;❌&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;auto_enums&lt;&#x2F;code&gt; crate&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
</description>
        </item>
        <item>
            <title>Futures Concurrency III: select!</title>
            <pubDate>Wed, 09 Feb 2022 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/futures-concurrency-3/</link>
            <guid>https://blog.yoshuawuyts.com/futures-concurrency-3/</guid>
            <description>&lt;p&gt;In our &lt;a href=&quot;&#x2F;futures-concurrency-2&quot;&gt;last post on futures concurrency&lt;&#x2F;a&gt; we talked
about the various ways futures in Rust can be awaited concurrently. But we
didn&#x27;t cover one mode: awaiting multiple futures concurrently and
resolving them as soon as they&#x27;re ready, without ever discarding any data.
This mode of concurrency is what is conventionally provided by the
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;latest&#x2F;futures&#x2F;macro.select.html&quot;&gt;&lt;code&gt;futures::select!{}&lt;&#x2F;code&gt; macro&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In this post we&#x27;re going to take a look at how this mode of concurrency works,
take a closer look at the issues &lt;code&gt;select! {}&lt;&#x2F;code&gt; has, discuss &lt;code&gt;Stream::merge&lt;&#x2F;code&gt; as
an alternative, and finally we&#x27;ll look at what the ergonomics might look like
in the future. This post is part of the &lt;em&gt;&quot;Futures Concurrency&quot;&lt;&#x2F;em&gt; series. You can find
all library code mentioned in this post as part of the
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-concurrency&quot;&gt;&lt;code&gt;futures-concurrency&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;process-concurrently-yield-sequentially&quot;&gt;process concurrently, yield sequentially&lt;&#x2F;h2&gt;
&lt;p&gt;In our last post we wrote an example where we raced multiple futures, and got
the output from the first future which resolves:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;delay&lt;&#x2F;span&gt;&lt;span&gt;(Duration::from_millis(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;delay&lt;&#x2F;span&gt;&lt;span&gt;(Duration::from_millis(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;delay&lt;&#x2F;span&gt;&lt;span&gt;(Duration::from_millis(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;300&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!([a, b, c].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;race&lt;&#x2F;span&gt;&lt;span&gt;().await, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using &lt;code&gt;race&lt;&#x2F;code&gt; gets the future &lt;code&gt;a&lt;&#x2F;code&gt; as soon as it resolves, but discards futures &lt;code&gt;b&lt;&#x2F;code&gt;
and &lt;code&gt;c&lt;&#x2F;code&gt;, making their content unavailable. If we don&#x27;t want to discard any futures
we can use &lt;code&gt;join&lt;&#x2F;code&gt;, but this requires waiting until &lt;em&gt;all&lt;&#x2F;em&gt; futures have been resolved
before we can operate on their output. What if we wanted something that sits
between the two: How can we get the result of all futures, but process them
one-by-one as soon as they&#x27;ve resolved?&lt;&#x2F;p&gt;
&lt;p&gt;If we pull up the table we introduced last post, we can now add a third column.
Instead of waiting for &lt;em&gt;all&lt;&#x2F;em&gt; outputs or just the &lt;em&gt;first&lt;&#x2F;em&gt; output,
we&#x27;re now handling all outputs one-by-one, as soon as they&#x27;re ready:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Wait for all outputs&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Wait for first output&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Handle output one-by-one&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Continue on error&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::join&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::try_race&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;???&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Return early on error&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::try_join&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::race&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;???&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;This is the table we&#x27;ve been working with so far, and it makes sense to continue
filling it out. But maybe if we disregard &quot;fallibility&quot; for a moment, there&#x27;s
another table we can create? Like &lt;code&gt;race&lt;&#x2F;code&gt; we start handling items as soon as the
first item is resolved, but instead of discarding the remaining items, like
&lt;code&gt;join&lt;&#x2F;code&gt; we are interested in &lt;em&gt;all&lt;&#x2F;em&gt; items:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Handle all items&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Discard some items&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Response starts on first item&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;???&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::race&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Response starts on last item&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::join&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;???&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;For the majority of this post we&#x27;ll be focusing on the top-left of this new
table: &quot;response starts on first item&quot; and &quot;handle all items&quot;. We&#x27;ll cover the
bottom right mode of concurrency towards the end of this post.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s start by taking a look at how the &lt;code&gt;futures&lt;&#x2F;code&gt; crate exposes this mode of
concurrency first.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-futures-select-macro&quot;&gt;the futures::select! macro&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;code&gt;futures&lt;&#x2F;code&gt; crate has a solution for this mode of concurrency through the
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-util&#x2F;0.3.17&#x2F;futures_util&#x2F;macro.select.html&quot;&gt;&lt;code&gt;select!{}&lt;&#x2F;code&gt;
macro&lt;&#x2F;a&gt;. The
&lt;code&gt;tokio&lt;&#x2F;code&gt; runtime also has a variant of &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio&#x2F;latest&#x2F;tokio&#x2F;macro.select.html&quot;&gt;&lt;code&gt;select! {}&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, but it behaves
slightly differently. Both the &lt;code&gt;futures&lt;&#x2F;code&gt; and &lt;code&gt;tokio&lt;&#x2F;code&gt; variants of &lt;code&gt;select&lt;&#x2F;code&gt; behave
largely the same, so the broader points we&#x27;re making apply to both. However
where relevant, we will look closer at how the two differ.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;select! {}&lt;&#x2F;code&gt; macro introduces a custom &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Domain-specific_language&quot;&gt;DSL&lt;&#x2F;a&gt; which resembles &lt;code&gt;match&lt;&#x2F;code&gt; blocks,
but with a few twists. Unlike a &lt;code&gt;match&lt;&#x2F;code&gt; block which takes a single input,
&lt;code&gt;select! {}&lt;&#x2F;code&gt; takes multiple futures, creates named bindings to them when they
resolve, and executes a block when it executes. It also has a &lt;code&gt;complete&lt;&#x2F;code&gt; case
(&lt;code&gt;else&lt;&#x2F;code&gt; in the &lt;code&gt;tokio&lt;&#x2F;code&gt; variant) which runs when no more data is available from
any of the input futures.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s a basic example of how &lt;code&gt;select!{}&lt;&#x2F;code&gt; is used, adapted from the &lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;async-book&#x2F;06_multiple_futures&#x2F;03_select.html&quot;&gt;async
book&lt;&#x2F;a&gt;.
This takes multiple asynchronous streams of numbers and sums them (&lt;a href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=stable&amp;amp;mode=debug&amp;amp;edition=2018&amp;amp;gist=1d3bd14cfaa61706a7fea4f135a60b77&quot;&gt;&lt;em&gt;playground&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures::stream::{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, StreamExt};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures::select;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create two streams of numbers. Both streams require being `fuse`d.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; a = stream::iter(vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;fuse&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; b = stream::iter(vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;]).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;fuse&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Initialize the output counter.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; total = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Process each item in the stream;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; break once there are no more items left to sum.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; item = select! {
&lt;&#x2F;span&gt;&lt;span&gt;        item = a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() =&amp;gt; item,  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 1. Get the next future in the stream,
&lt;&#x2F;span&gt;&lt;span&gt;        item = b.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() =&amp;gt; item,  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;    assign its `Output` to `item` when it resolves.
&lt;&#x2F;span&gt;&lt;span&gt;        complete =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;,        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 2. The `complete` case runs when both streams are exhausted. 
&lt;&#x2F;span&gt;&lt;span&gt;    };
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span&gt;Some(num) = item {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Increment the counter with the value from the stream.
&lt;&#x2F;span&gt;&lt;span&gt;        total += num;             
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Validate the result.
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(total, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;21&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This example is simplified. It can roughly be broken into three steps:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Create the streams and &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;latest&#x2F;futures&#x2F;prelude&#x2F;stream&#x2F;trait.StreamExt.html#method.fuse&quot;&gt;&lt;code&gt;fuse&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; them. &lt;code&gt;fuse&lt;&#x2F;code&gt; makes it so once a &lt;code&gt;Stream&lt;&#x2F;code&gt;
returns &lt;code&gt;None&lt;&#x2F;code&gt;, it guarantees to keep returning &lt;code&gt;None&lt;&#x2F;code&gt; instead of potentially panicking &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#panic&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Create the main processing loop using &lt;code&gt;select!&lt;&#x2F;code&gt;, summing the numbers together.&lt;&#x2F;li&gt;
&lt;li&gt;Validate the result is correct.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;panic&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Unfused streams are not guaranteed to panic if they are accessed again
after they&#x27;ve been exhausted. But they definitely &lt;em&gt;can&lt;&#x2F;em&gt; panic, and it&#x27;s not
unlikely that when we have generators they will, just like &lt;code&gt;Future&lt;&#x2F;code&gt;, panic if
they&#x27;re called again after they&#x27;ve been exhausted.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;issues-with-futures-select&quot;&gt;Issues with futures::select!&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we&#x27;ve talked about the &lt;code&gt;select! {}&lt;&#x2F;code&gt; macro and the mode of concurrency
it enables, it&#x27;s time we start looking at the issues with it. Because oh boy are
there many. My personal opinion has always been that &lt;code&gt;select! {}&lt;&#x2F;code&gt; seems hard to
use, and feels off. But in writing this post I&#x27;ve had to substantiate this
feeling with actual evidence, and I don&#x27;t like what I&#x27;ve learned. Not. At. All.&lt;&#x2F;p&gt;
&lt;p&gt;In this section we&#x27;ll cover different aspects of how &lt;code&gt;select! {}&lt;&#x2F;code&gt; falls short.
But if you want my brief, summarized opinion: &lt;strong&gt;I view &lt;code&gt;select! {}&lt;&#x2F;code&gt; as easy to
misuse, hard to debug, difficult to learn, when used &lt;em&gt;correctly&lt;&#x2F;em&gt; makes for
incredibly hard-to-read code, and seems unlikely to being included in the stdlib
or language.&lt;&#x2F;strong&gt; I think this qualifies as a &lt;em&gt;strong statement&lt;&#x2F;em&gt;. Now let me back
it up by sharing my reasoning for each part.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;modifying-hello-world-can-lead-to-data-loss&quot;&gt;modifying &quot;hello world&quot; can lead to data loss&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;select! {}&lt;&#x2F;code&gt; is not limited to implementing a single form of concurrency: it is
flexible enough that it can be used to implement different concurrency
primitives. This makes it hard for both the compiler and humans to validate
whether it&#x27;s used correctly. Which is not great when performing concurrent
operations in a potentially multi-threaded system. This can be exceptionally
hard to debug.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s take our earlier example, and instead of taking numbers from a stream and
incrementing a counter, let&#x27;s do something we might encounter in the real-world.
For example, in one select arm we may want to process items from a stream, and in
the other we may want to read data from some handle and send it into a channel:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; before
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; item = select! {
&lt;&#x2F;span&gt;&lt;span&gt;        item = a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() =&amp;gt; item,
&lt;&#x2F;span&gt;&lt;span&gt;        item = b.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() =&amp;gt; item,
&lt;&#x2F;span&gt;&lt;span&gt;        complete =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    };
&lt;&#x2F;span&gt;&lt;span&gt;    ...
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; after
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    futures::select! {
&lt;&#x2F;span&gt;&lt;span&gt;        _ =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_send&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; handle, &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; channel).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;fuse&lt;&#x2F;span&gt;&lt;span&gt;() =&amp;gt; {} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; read data from a handle and send it to a channel
&lt;&#x2F;span&gt;&lt;span&gt;        item =&amp;gt; stream.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() =&amp;gt; { ... }                       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; process data from a stream
&lt;&#x2F;span&gt;&lt;span&gt;        complete =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;,                                     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; all work completed, stop the loop
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you squint you can see that the shape of both loops remained roughly the
same. The most significant change is that instead of calling &lt;code&gt;stream.next()&lt;&#x2F;code&gt;
in both arms, we have switched out one arm to use &lt;code&gt;read_send&lt;&#x2F;code&gt; instead. We can no
longer rely on the futures being fused, so we need to manually do that on the
future now instead. But what you probably didn&#x27;t expect is that this code is
fundamentally broken, and your program &lt;em&gt;will&lt;&#x2F;em&gt; lose data.&lt;&#x2F;p&gt;
&lt;p&gt;The second example is the exact pattern &lt;a href=&quot;https:&#x2F;&#x2F;tomaka.medium.com&#x2F;a-look-back-at-asynchronous-rust-d54d63934a1c&quot;&gt;Tomaka covers in their 2021 post on async
Rust&lt;&#x2F;a&gt;. They based this post on their experience writing production async
Rust code for several years, and described this issue as follows (emphasis is
Tomaka&#x27;s):&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;It is always possible to solve this problem in some way, but what I would like
to highlight is an even bigger problem: &lt;strong&gt;these kind of cancellation issues are
hard to spot and debug&lt;&#x2F;strong&gt;. In the problematic example, all you will observe is that
in some rare occasions some parts of the file seem to be skipped. There will not
be any panic or any clear indication of where the problem could come from. &lt;strong&gt;This
is the worst kind of bugs you can encounter.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;What&#x27;s happening here is that we intended to express: &quot;process concurrently,
yield sequentially&quot; semantics. But what we ended up writing was &quot;race&quot;
semantics. The reason for this is that &lt;code&gt;read_send&lt;&#x2F;code&gt; and &lt;code&gt;stream.next()&lt;&#x2F;code&gt; are
racing, and if &lt;code&gt;stream.next()&lt;&#x2F;code&gt; completes first, the &lt;code&gt;read_send&lt;&#x2F;code&gt; future is
discarded. This can lead to data from &lt;code&gt;handle&lt;&#x2F;code&gt; having being read, but not yet
sent into the &lt;code&gt;channel&lt;&#x2F;code&gt;. Which means the next time we read data from &lt;code&gt;handle&lt;&#x2F;code&gt;,
the cursor will have advanced, and data is now lost.&lt;&#x2F;p&gt;
&lt;p&gt;You may be wondering why &lt;code&gt;stream.next()&lt;&#x2F;code&gt; &lt;em&gt;does&lt;&#x2F;em&gt; work, but &lt;code&gt;read_send&lt;&#x2F;code&gt; does not.
The short explanation is that the state of the &lt;code&gt;stream.next&lt;&#x2F;code&gt; future is entirely
contained within &lt;code&gt;stream&lt;&#x2F;code&gt;. Which means that if we re-create the future on each
iteration, we can continue right where we left off. &lt;code&gt;read_send&lt;&#x2F;code&gt; on the contrary
has state local to the future. Which means when we recreate the future, we lose
that state, regardless of how far we got.&lt;&#x2F;p&gt;
&lt;p&gt;In their post Tomaka appears to primarily attribute the issue they&#x27;re
experiencing to all futures being cancellable. And that makes sense: if future
can&#x27;t be cancelled, it can&#x27;t lead to data loss. And if &lt;code&gt;select!&lt;&#x2F;code&gt; only ever
operates un cancellable futures, then we&#x27;ve successfully guarded against this
issue! But in my opinion the issue is less with all futures being cancellable
(&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-cancellation-1&#x2F;#an-async-trait-which-can-t-be-cancelled&quot;&gt;I think this is
good&lt;&#x2F;a&gt;),
but instead that depending on how you configure &lt;code&gt;select!&lt;&#x2F;code&gt; you may
unintentionally be presented with &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;latest&#x2F;async_std&#x2F;future&#x2F;trait.Future.html#method.race&quot;&gt;&quot;race&quot; semantics&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;In general I&#x27;d recommend folks don&#x27;t attempt to use &lt;code&gt;select!&lt;&#x2F;code&gt; for this mode of
concurrency and instead spawn (local) tasks instead. This is
largely how over the years I&#x27;ve avoided to ever have to write &lt;code&gt;select!&lt;&#x2F;code&gt; statements using
futures. But because we&#x27;re talking about the issues with &lt;code&gt;select!&lt;&#x2F;code&gt; we
should at least take a look at what a correct solution using &lt;code&gt;select!&lt;&#x2F;code&gt; might
look like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create the future we&amp;#39;re polling once, outside the loop so it
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; doesn&amp;#39;t drop between iterations.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; read_send_fut = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_send&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; handle, &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; channel);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    futures::select! {
&lt;&#x2F;span&gt;&lt;span&gt;        _ =&amp;gt; read_send_fut =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Whenever the last future resolves, we need to re-create it for the next loop.
&lt;&#x2F;span&gt;&lt;span&gt;            read_send_fut = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_send&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; handle, &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; channel);
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;        item =&amp;gt; stream.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() =&amp;gt; { ... }
&lt;&#x2F;span&gt;&lt;span&gt;        complete =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let me be honest: I don&#x27;t feel good about this solution. We&#x27;re instantiating the
exact same future in two separate places. And because this is an example, we&#x27;re
lucky in this case that we only do this for the one future. In real-world
examples we might want to repeat this more often. We could probably abstract the
future instantiation using a function. But I&#x27;m hesitant to introduce further
abstractions.&lt;&#x2F;p&gt;
&lt;p&gt;To me this code feels brittle, riddled with assumptions which are not directly
obvious from the code, and it&#x27;s becoming hard to see what it is that we&#x27;re
&lt;em&gt;actually&lt;&#x2F;em&gt; trying to do here. And that&#x27;s an issue. &lt;code&gt;select!&lt;&#x2F;code&gt; is so flexible, it
stops being able to accurately capture &lt;em&gt;intent&lt;&#x2F;em&gt;. This makes it impossible for
the compiler to validate we&#x27;re using it right. And hard for people reading the
code to understand what we&#x27;re trying to do. &lt;strong&gt;Because it&#x27;s possible to mis-use
&lt;code&gt;select!&lt;&#x2F;code&gt; it means that any diligent code-reviewer will manually need to
validate &lt;code&gt;select!&lt;&#x2F;code&gt; blocks are right, every time they&#x27;re modified. Because the
consequences of failing to do so can have very real consequences.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;An alternative to &lt;code&gt;select! {}&lt;&#x2F;code&gt; should only expose a single concurrency mode from
its API, making it impossible to accidentally opt-in to a different mode. One of
Rust&#x27;s core strengths is the ability for the compiler to validate our usage of
APIs is correct. And for something as fundamental as a concurrency mode we should
absolutely be making use of this.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;halt-points-are-hidden-in-a-macro&quot;&gt;halt points are hidden in a macro&lt;&#x2F;h3&gt;
&lt;p&gt;In &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-cancellation-1&#x2F;#halt-safety&quot;&gt;my post on async cancellation&lt;&#x2F;a&gt;, I
showed the following example displaying every point where code can be halted.
You can think of &quot;halting&quot; as &quot;this is where the function will potentially stop
executing, so we need to think about how to clean up local state when it does&quot;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Regardless of where in the function we stop execution, destructors will be
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; run and resources will be cleaned up.
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;do_something&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: PathBuf) -&amp;gt; io::Result&amp;lt;Output&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;                                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 1. the future is not guaranteed to progress after instantiation
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; file = fs::open(&amp;amp;path).await?;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 2. `.await` and 3. `?` can cause the function to halt
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;parse&lt;&#x2F;span&gt;&lt;span&gt;(file).await;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 4. `.await` can cause the function to halt
&lt;&#x2F;span&gt;&lt;span&gt;    res                                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 5. execution has finished, return a value
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Something which makes &lt;code&gt;select! {}&lt;&#x2F;code&gt; difficult to reason about with regards to
halting (and cancellation) is that it obfuscates potential halt points by not requiring that they
are marked with &lt;code&gt;.await&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; item = select! {
&lt;&#x2F;span&gt;&lt;span&gt;        item = a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() =&amp;gt; item, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 1. .await is hidden here, which can cause a halt
&lt;&#x2F;span&gt;&lt;span&gt;        item = b.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() =&amp;gt; item, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 2. .await is hidden here, which can cause a halt
&lt;&#x2F;span&gt;&lt;span&gt;        complete =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    };
&lt;&#x2F;span&gt;&lt;span&gt;    ...
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Generally the rule is that halt points contained in function bodies are
annotated using &lt;code&gt;?&lt;&#x2F;code&gt; or &lt;code&gt;.await&lt;&#x2F;code&gt;. But &lt;code&gt;select!&lt;&#x2F;code&gt; hides &lt;code&gt;.await&lt;&#x2F;code&gt; statements
internally, meaning they can no longer be seen in in the function body. Someone
unfamiliar with &lt;code&gt;select!&lt;&#x2F;code&gt;&#x27;s semantics may not expect it to cause the function to
halt, which can lead to bugs. An alternative to &lt;code&gt;select! {}&lt;&#x2F;code&gt; should use &lt;code&gt;.await&lt;&#x2F;code&gt;
to annotate it can halt.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;fuse-requirements&quot;&gt;&lt;code&gt;fuse&lt;&#x2F;code&gt; requirements&lt;&#x2F;h3&gt;
&lt;p&gt;When a &lt;code&gt;Future&lt;&#x2F;code&gt; is created through using the &lt;code&gt;async&lt;&#x2F;code&gt; keyword, if it&#x27;s polled after
it&#x27;s been completed, it will panic. Similarly, once we have generators in the
language, creating a &lt;code&gt;Stream&lt;&#x2F;code&gt; through an &lt;code&gt;async gen fn&lt;&#x2F;code&gt; we would logically
expect that to panic too if we call it after it&#x27;s been completed &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#compile-time&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;compile-time&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;The compiler guards against &quot;poll-after-completion&quot; errors in
most cases because &lt;code&gt;.await&lt;&#x2F;code&gt; takes ownership of futures. This means if you call &lt;code&gt;.await&lt;&#x2F;code&gt;
twice on the same future, it&#x27;ll fail to compile with a &quot;use of moved value&quot;
error. The &quot;panic if this future is polled after it&#x27;s completed&quot; error is kind
of like the runtime version of the move semantics guard, for when a future is
manually polled to completion. While not required by the &lt;code&gt;Future&lt;&#x2F;code&gt; trait, I think
it&#x27;s good practice for most futures to implement similar &quot;poll-after-completion&quot;
behavior as futures created through the &lt;code&gt;async&lt;&#x2F;code&gt; keyword.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&quot;fuse semantics&quot; mean slightly different things for futures, iterators, and streams:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Future&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt;: after a future has returned &lt;code&gt;Poll::Ready&lt;&#x2F;code&gt; once, keep returning
&lt;code&gt;Poll::Pending&lt;&#x2F;code&gt; instead of panicking(&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-util&#x2F;0.3.19&#x2F;src&#x2F;futures_util&#x2F;future&#x2F;future&#x2F;fuse.rs.html#80-93&quot;&gt;ref&lt;&#x2F;a&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Iterator&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt;: after an iterator has returned &lt;code&gt;None&lt;&#x2F;code&gt; once, keep returning &lt;code&gt;None&lt;&#x2F;code&gt;
instead of panicking (&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;struct.Fuse.html#impl-Iterator&quot;&gt;ref&lt;&#x2F;a&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Stream&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt;: after a stream has returned &lt;code&gt;Poll::Ready(None)&lt;&#x2F;code&gt; once, keep
returning &lt;code&gt;Poll::Ready(None)&lt;&#x2F;code&gt; instead of
panicking (&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-util&#x2F;0.3.19&#x2F;src&#x2F;futures_util&#x2F;stream&#x2F;stream&#x2F;fuse.rs.html#43-67&quot;&gt;ref&lt;&#x2F;a&gt;).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Futures passed to &lt;code&gt;select!&lt;&#x2F;code&gt; must implement fuse semantics so that we can track
the completion status of each individual future. If we poll a future and it This cannot
be tracked inside the &lt;code&gt;select! {}&lt;&#x2F;code&gt; macro because &lt;code&gt;select! {}&lt;&#x2F;code&gt; does not take
ownership of individual futures. Once a &lt;code&gt;select! {}&lt;&#x2F;code&gt; block has yielded, the
futures within it can be accessed again, which is often used to pass them back
into another &lt;code&gt;select! {}&lt;&#x2F;code&gt; macro on a subsequent loop.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Does my future implement fuse semantics&quot; is checked during compilation &lt;a href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=stable&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=4db0ef61a23142311a99630c81e8c045&quot;&gt;in the
&lt;code&gt;futures::select!&lt;&#x2F;code&gt;
macro&lt;&#x2F;a&gt;,
but left as an exercise to the user &lt;a href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=stable&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=b1d4808a308f2077d8a47ed6edca2209&quot;&gt;when using
&lt;code&gt;tokio::select!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
This makes the &lt;code&gt;futures&lt;&#x2F;code&gt; variant more resilient than the &lt;code&gt;tokio&lt;&#x2F;code&gt; variant, but in
both cases it&#x27;s annoying that we have to care about this at all because &lt;code&gt;Future&lt;&#x2F;code&gt;
and &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; were not designed to default to implement fuse semantics.&lt;&#x2F;p&gt;
&lt;p&gt;This mismatch causes &lt;code&gt;select! {}&lt;&#x2F;code&gt; requires users to need to educate themselves
on what fusing futures is, how to do it, and how not to be caught by runtime
errors. &lt;code&gt;select! {}&lt;&#x2F;code&gt; as an abstraction does not fit well with the rest of async
Rust, and as a result users end up needing to learn how to work around this
mismatch. Which does not make for a great experience, and would be great if we
could evade front-loading when teaching folks about async Rust.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;trait-signatures&quot;&gt;trait signatures&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;select! {}&lt;&#x2F;code&gt; can not only operate on futures, it can operate on asynchronous
streams too. There is no real counterpart to &lt;code&gt;Future&lt;&#x2F;code&gt; in the stdlib (the syn
version of &quot;asynchronous value&quot; is just &quot;a value&quot;), but the counterpart to
&lt;code&gt;AsyncIterator&lt;&#x2F;code&gt; (née: &lt;code&gt;Stream&lt;&#x2F;code&gt;) is &lt;code&gt;Iterator&lt;&#x2F;code&gt;. An unfortunate consequence of
&lt;code&gt;select! {}&lt;&#x2F;code&gt; is that it has lead to a mismatch between the signatures of
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.3.17&#x2F;futures&#x2F;stream&#x2F;trait.FusedStream.html&quot;&gt;&lt;code&gt;futures::FusedStream&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
and &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.FusedIterator.html&quot;&gt;&lt;code&gt;FusedIterator&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
&lt;code&gt;FusedStream&lt;&#x2F;code&gt; has a mandatory method: &lt;code&gt;is_terminated&lt;&#x2F;code&gt; which needs to be
implemented. &lt;code&gt;FusedIterator&lt;&#x2F;code&gt; does not have this method.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;is_terminated&lt;&#x2F;code&gt; method on &lt;code&gt;Future&lt;&#x2F;code&gt; allows a third state to be represented in
the &lt;code&gt;Future&lt;&#x2F;code&gt; poll model: &quot;this future has completed&quot;. For &lt;code&gt;Stream&lt;&#x2F;code&gt; we can
represent this state by yielding &lt;code&gt;Poll::Ready(None)&lt;&#x2F;code&gt;. But in &lt;code&gt;Future&lt;&#x2F;code&gt; we only
have the choice between &lt;code&gt;Poll::Ready(T)&lt;&#x2F;code&gt; and &lt;code&gt;Poll::Pending&lt;&#x2F;code&gt;, neither of which
means &quot;I&#x27;m done&quot;. As remarked in &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;futures-rs&#x2F;issues&#x2F;1219#issue-352317333&quot;&gt;the original issue discussing &lt;code&gt;FusedFuture&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;,
the need for having the &lt;code&gt;is_terminated&lt;&#x2F;code&gt; method would go away if &lt;code&gt;select! {}&lt;&#x2F;code&gt;
would have an internal &lt;code&gt;loop&lt;&#x2F;code&gt; statement. If the loop lives internally, state
tracking can be moved interally as well, and we no longer have the same issues.
But unfortunately &lt;code&gt;select_loop!&lt;&#x2F;code&gt; was deemed as &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;futures-rs&#x2F;issues&#x2F;1219#issuecomment-414834102&quot;&gt;being too
inflexible&lt;&#x2F;a&gt;,
and instead the choice was made to go with &lt;code&gt;FusedFuture&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;FusedStream&lt;&#x2F;code&gt;
instead &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#history&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;history&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;code&gt;select_loop!&lt;&#x2F;code&gt; is &lt;em&gt;so close&lt;&#x2F;em&gt; to what we&#x27;re proposing as
the solution in this post. I only found out about it towards the end of editing
this post, but it feels like this was just a few iterations away from what we&#x27;re
proposing we do here instead.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;The reason why discussing trait mismatches is important is because a guiding principle for of the async
foundations WG is &lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;wg-async-foundations&#x2F;vision&#x2F;how_it_feels.html#consistent-just-add-asyncawait&quot;&gt;parity between sync and async
Rust&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Async Rust should be a small delta atop Sync Rust. People who are familiar
with sync Rust should be able to leverage what they know to make adopting Async
Rust straightforward. Porting a sync code base to async should be relatively
smooth: just add async&#x2F;await, adopt the async variants of the various libraries,
and you&#x27;re done.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Introducing &lt;code&gt;FusedFuture&lt;&#x2F;code&gt;, &lt;code&gt;FusedStream&lt;&#x2F;code&gt; and &lt;code&gt;select! {}&lt;&#x2F;code&gt; into the stdlib would
mean we&#x27;d need to take one of three decisions:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;We accept that &lt;code&gt;FusedStream&lt;&#x2F;code&gt; and &lt;code&gt;FusedIterator&lt;&#x2F;code&gt; have a different signature,
and &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-overloading&#x2F;&quot;&gt;all the consequences that carries regarding parity with std
rust&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;We re-work &lt;code&gt;select! {}&lt;&#x2F;code&gt; to not rely on &lt;code&gt;FusedFuture::is_terminated&lt;&#x2F;code&gt;.
I believe this has been tried though, and it didn&#x27;t work out.&lt;&#x2F;li&gt;
&lt;li&gt;We re-work &lt;code&gt;select! {}&lt;&#x2F;code&gt; to not require fuse semantics. This would require
&lt;code&gt;select! {}&lt;&#x2F;code&gt; take ownership of futures, which would lead to data loss.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;code&gt;select! {}&lt;&#x2F;code&gt;&#x27;s relationship to the &lt;code&gt;Fused&lt;&#x2F;code&gt; traits is not good, and all options
how to resolve it carry distinct downsides. The best solution would be to look
for alternatives to &lt;code&gt;select! {}&lt;&#x2F;code&gt; which implement the same concurrency mode, but
do not rely on fuse semantics on the types they operate on.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;debugging-errors-is-hard&quot;&gt;debugging errors is hard&lt;&#x2F;h3&gt;
&lt;p&gt;If you misuse &lt;code&gt;select! {}&lt;&#x2F;code&gt;, how do you find out? Implementing &lt;code&gt;race&lt;&#x2F;code&gt; semantics
where you didn&#x27;t mean will lead to data &lt;em&gt;occasionally&lt;&#x2F;em&gt; being discarded.
Depending on the data you&#x27;re reading this can lead to hard-to-detect bugs.
There&#x27;s no guarantees errors will be thrown, it&#x27;s not obvious from the code
that we&#x27;re racing, and we have few (if any) tools or lints to detect races like
these. The best chance at catching issues with this before they occur is to have a
thorough test suite which can pinpoint this error before it&#x27;s shipped. But in my
experience this is not a given.&lt;&#x2F;p&gt;
&lt;p&gt;Debugging work is often 90% understanding the bug, and 10% fixing the bug. And
in order to catch bugs with &lt;code&gt;select! {}&lt;&#x2F;code&gt; you need to understand how the macro
works, how async cancellation works in Rust, find out exactly where it&#x27;s used,
and finally: employ a fix. This is the type of work that even experts in async
Rust might struggle with (hi).&lt;&#x2F;p&gt;
&lt;p&gt;It doesn&#x27;t mean that we can&#x27;t do anything about this though. We could apply
runtime probing to find out where futures are being cancelled in a loop. Or
static lints which catch potential mis-configurations of &lt;code&gt;select! {}&lt;&#x2F;code&gt;. But
that&#x27;s speculation, and will never be as good a fix as having APIs where bad
states are unrepresentable.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;select-and-the-stdlib&quot;&gt;&lt;code&gt;select!&lt;&#x2F;code&gt; and the stdlib&lt;&#x2F;h3&gt;
&lt;p&gt;Objectively &lt;code&gt;select! {}&lt;&#x2F;code&gt; has many other issues, the first being its relation to the
stdlib. As we&#x27;re looking to &lt;a href=&quot;https:&#x2F;&#x2F;www.ncameron.org&#x2F;blog&#x2F;portable-and-interoperable-async-rust&#x2F;&quot;&gt;add more async functionality to the
stdlib&lt;&#x2F;a&gt;,
foundational components for async concurrency will be part of this. So it&#x27;s
worth asking how we could add &lt;code&gt;select! {}&lt;&#x2F;code&gt;&#x27;s functionality to the stdlib.&lt;&#x2F;p&gt;
&lt;p&gt;Introducing &lt;code&gt;select! {}&lt;&#x2F;code&gt; as a macro would be the first option. But if we
introduced it today, it would immediately become one of the most complicated
macros in the stdlib. &lt;code&gt;select! {}&lt;&#x2F;code&gt; really is shaped like a control-flow
primitive, and Rust tends to prefer keywords over macros for control flow
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#keywords&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Rust cares deeply about diagnostics, and for something as
fundamental as control flow we would want to provide comprehensive errors,
explainers, and suggestions.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;keywords&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;The &lt;code&gt;try!&lt;&#x2F;code&gt; macro became &lt;code&gt;?&lt;&#x2F;code&gt;. The &lt;code&gt;await!&lt;&#x2F;code&gt; macro became &lt;code&gt;.await&lt;&#x2F;code&gt;.
Control flow constructs in Rust tend to be introduced as keywords
instead, but the bar for those is incredibly high.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Adding &lt;code&gt;select&lt;&#x2F;code&gt; as a keyword to Rust would possibly be harder; the barrier for
keywords in Rust is incredibly high. In order for a new keyword to be
introduced, an irrefutable case must be presented. For &lt;code&gt;.await&lt;&#x2F;code&gt; we
proved that it enabled things that could otherwise only be done using &lt;code&gt;unsafe&lt;&#x2F;code&gt;.
&lt;code&gt;const&lt;&#x2F;code&gt; in generic position were added because it enabled computation within the
type system. &lt;code&gt;select&lt;&#x2F;code&gt; in comparison merely adds a fifth mode of concurrency to
async Rust &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#crossbeam&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. This is hardly comparable in impact. Especially if we can
prove that we can provide the same concurrency primitives entirely using library
functions.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;crossbeam&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;crossbeam-channel&#x2F;0.5.1&#x2F;crossbeam_channel&#x2F;macro.select.html&quot;&gt;&lt;code&gt;crossbeam_channel::select&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
exists for non-async Rust and is similar in shape. But it operates
over channels only, and cannot yet be mixed with async Rust. Any
proposal for a &lt;code&gt;select&lt;&#x2F;code&gt; keyword would need to carefully consider
how &lt;code&gt;select&lt;&#x2F;code&gt; would interact with both async and non-async Rust.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;concurrent-stream-processing-with-stream-merge&quot;&gt;concurrent stream processing with &lt;code&gt;Stream::merge&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;So far we&#x27;ve taken a look at the mode of concurrency we&#x27;re trying to implement,
and the issues the &lt;code&gt;select! {}&lt;&#x2F;code&gt; macro has. This is the part where we move past
that and show a surprisingly simple alternative solution to this type of
concurrency: &lt;code&gt;Stream::merge&lt;&#x2F;code&gt;. We&#x27;ll be stepping away from futures for a second
to talk about streams, but we&#x27;ll get back how this relates to futures as well in
a bit.&lt;&#x2F;p&gt;
&lt;p&gt;Fundamentally what we want to be doing is awaiting multiple streams concurrently;
processing items from either stream as soon as they&#x27;re ready. In &lt;code&gt;async-std&lt;&#x2F;code&gt;
we introduced &lt;code&gt;Stream::merge&lt;&#x2F;code&gt; about two years ago (!) for this exact purpose.
It now also exists in &lt;code&gt;futures-concurrency&lt;&#x2F;code&gt;, the companion library to this
series. But for this example we&#x27;ll stick to &lt;code&gt;async-std&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The way &lt;code&gt;Stream::merge&lt;&#x2F;code&gt; works is that it takes two streams, and &lt;em&gt;merges&lt;&#x2F;em&gt; them as
if they were a single stream. Data comes out as soon as it&#x27;s ready, and can be
handled just like any other stream:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::stream;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Declare our streams.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = stream::iter(vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = stream::iter(vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Initialize the output counter.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; total = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Combine both streams, and add each value to the total.
&lt;&#x2F;span&gt;&lt;span&gt;a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;merge&lt;&#x2F;span&gt;&lt;span&gt;(b).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;for_each&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;num&lt;&#x2F;span&gt;&lt;span&gt;| total += num).await;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Validate the result.
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(total, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;21&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This code is functionally equivalent to the &lt;code&gt;select! {}&lt;&#x2F;code&gt; loop we introduced
at the start of this post. Except it&#x27;s &lt;em&gt;significantly&lt;&#x2F;em&gt; less code, does not require
manually &lt;code&gt;fuse&lt;&#x2F;code&gt;ing streams (&lt;code&gt;Merge&lt;&#x2F;code&gt; tracks the state), and importantly: does
not introduce any new syntax [^gripe].&lt;&#x2F;p&gt;
&lt;p&gt;This is not even the shortest version this can be, using the
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.10.0&#x2F;async_std&#x2F;stream&#x2F;trait.Sum.html&quot;&gt;&lt;code&gt;stream::Sum&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; trait
we can shorten this specific example to:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::stream;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = stream::from_iter(vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = stream::from_iter(vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;merge&lt;&#x2F;span&gt;&lt;span&gt;(b).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;().await, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;21&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Conceptually this seems so simple, it almost feels too good to be true. But it
isn&#x27;t: there are no hidden &lt;code&gt;Unpin&lt;&#x2F;code&gt; bounds, no secret &lt;code&gt;FusedStream&lt;&#x2F;code&gt; requirements,
or unexpected gotchas. We got to this solution by closely analyzing the mode of
concurrency &lt;code&gt;select! {}&lt;&#x2F;code&gt; exposes, and finding prior art for it in
&lt;a href=&quot;https:&#x2F;&#x2F;www.learnrxjs.io&#x2F;learn-rxjs&#x2F;operators&#x2F;combination&#x2F;merge&quot;&gt;rxjs&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;concurrently-processing-a-mix-of-futures-and-streams&quot;&gt;Concurrently processing a mix of futures and streams&lt;&#x2F;h2&gt;
&lt;p&gt;Perhaps you&#x27;re wondering whether &lt;code&gt;Stream::merge&lt;&#x2F;code&gt; can only replace &lt;code&gt;select! {}&lt;&#x2F;code&gt;
loops in simple cases. What about differently-typed streams with different
signatures and individual futures mixed in. That&#x27;s exactly what &lt;code&gt;select! {}&lt;&#x2F;code&gt; was
designed for. For the sake of brevity I&#x27;ll skip the &lt;code&gt;select! {}&lt;&#x2F;code&gt; variant and
only show how well &lt;code&gt;Stream::merge&lt;&#x2F;code&gt; is capable of handling this&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#limit&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;limit&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;This reminds me we made mistakes in &lt;code&gt;async-std&lt;&#x2F;code&gt;. &lt;code&gt;stream::once&lt;&#x2F;code&gt; really
should be able to take a &lt;code&gt;Future&lt;&#x2F;code&gt; rather than a regular value. This example
pretends we didn&#x27;t make that mistake.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::stream;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create a shared output enum, used by all stream.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;Message {
&lt;&#x2F;span&gt;&lt;span&gt;    Num(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    Text(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static str&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create a variety of streams from futures and iterators, and map them to the
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; same output type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = stream::from_iter([&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(Message::Num);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = stream::from_iter([&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;chashu&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;nori&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;]).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(Message::Text);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = stream::once(async { &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; }).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(Message::Text);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Merge all streams and handle each output one-by-one.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; s = a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;merge&lt;&#x2F;span&gt;&lt;span&gt;(b).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;merge&lt;&#x2F;span&gt;&lt;span&gt;(c);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(msg) = s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().await {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; msg {
&lt;&#x2F;span&gt;&lt;span&gt;        Num(n) =&amp;gt; println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;received a number: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, n),
&lt;&#x2F;span&gt;&lt;span&gt;        Text(s) =&amp;gt; println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;received a string: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, s),
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can even add short-circuiting by using a generalized abort mechanism like
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;stop-token&#x2F;0.2.0&#x2F;stop_token&#x2F;&quot;&gt;&lt;code&gt;stop-token&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, or adding
another enum variant that maps to &lt;code&gt;break&lt;&#x2F;code&gt; whenever called.&lt;&#x2F;p&gt;
&lt;p&gt;This shows how &lt;code&gt;Stream::merge&lt;&#x2F;code&gt; implements the &quot;process items as soon
as they&#x27;re available&quot; mode of concurrency, the same as &lt;code&gt;select! {}&lt;&#x2F;code&gt;. And
importantly, it does so using regular Rust types and techniques.&lt;&#x2F;p&gt;
&lt;p&gt;The least comfortable part of what we&#x27;ve written is type unification using &lt;code&gt;enum Message {}&lt;&#x2F;code&gt; and &lt;code&gt;map(Message::Type)&lt;&#x2F;code&gt;. But making sure types align is a common
Rust issue, and using an enum for that is the common solution. The
semantics here are a lot less &lt;em&gt;special&lt;&#x2F;em&gt; than those introduced by &lt;code&gt;select! {}&lt;&#x2F;code&gt;,
which should make this significantly easier to get the hang of. Especially if we
document it right.&lt;&#x2F;p&gt;
&lt;p&gt;If we&#x27;re thinking about a future where the stdlib provides a &lt;em&gt;complete&lt;&#x2F;em&gt; solution
for futures concurrency out of the box, then the options for &lt;code&gt;select! {}&lt;&#x2F;code&gt; look
rather unappealing. We could choose to ship the macro as-is, and forever deal
with manual &lt;code&gt;fuse&lt;&#x2F;code&gt; calls, diverging traits
[&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.FusedIterator.html&quot;&gt;1&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.3.17&#x2F;futures&#x2F;stream&#x2F;trait.FusedStream.html&quot;&gt;2&lt;&#x2F;a&gt;], and daunting errors.&lt;&#x2F;p&gt;
&lt;p&gt;Or we could promote &lt;code&gt;select&lt;&#x2F;code&gt; into a keyword. This could do away with the
requirement to manually invoke &lt;code&gt;fuse&lt;&#x2F;code&gt; for us. But would come with the downside
that we now have a syntax which is unlike anything else. The arms are different
from those found in &lt;code&gt;match&lt;&#x2F;code&gt;, and it would likely be uniquely scoped to async
contexts. Introducing new keywords is an &lt;em&gt;incredibly&lt;&#x2F;em&gt; high barrier to clear, and
have my doubts whether &lt;code&gt;select&lt;&#x2F;code&gt; could make it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;concurrently-processing-futures-in-a-loop&quot;&gt;Concurrently processing futures in a loop&lt;&#x2F;h2&gt;
&lt;p&gt;Earlier in this post we looked at Tomaka&#x27;s post which &lt;a href=&quot;https:&#x2F;&#x2F;tomaka.medium.com&#x2F;a-look-back-at-asynchronous-rust-d54d63934a1c#3008&quot;&gt;featured data-loss issues with
&lt;code&gt;select! {}&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
Let&#x27;s bring up the example verbatim from the post:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; open our IO types
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; file = ...;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; channel = ...;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; This loop re-creates the `read_send` future on each iteration. That means if
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `socket.read_packet` completes, `read_send` may have read data from the file,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; but not finished writing it to a channel, which can lead to data loss
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    futures::select! {
&lt;&#x2F;span&gt;&lt;span&gt;        _ =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_send&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; file, &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; channel) =&amp;gt; {}, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; uh oh, data loss can happen here
&lt;&#x2F;span&gt;&lt;span&gt;        some_data =&amp;gt; socket.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_packet&lt;&#x2F;span&gt;&lt;span&gt;() =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ...
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The issue was that we accidentally opted into &quot;race&quot; semantics
when we didn&#x27;t mean to, which could lead to data loss. In their post, Tomaka
mentions there are different ways of solving this, including my personal choice:
&lt;a href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=stable&amp;amp;mode=debug&amp;amp;edition=2018&amp;amp;gist=9ea13a3f413740f4fefd419f2c0224d1&quot;&gt;spawn each individual operation on a separate task and await
them&lt;&#x2F;a&gt;
But for the sake of example, let&#x27;s take a look at how we can implement the logic above using &lt;code&gt;Stream::merge&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; open our IO types
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; file = ...;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; channel = ...;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create our shared message type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;Message {
&lt;&#x2F;span&gt;&lt;span&gt;    None,
&lt;&#x2F;span&gt;&lt;span&gt;    Data&amp;lt;Vec&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create two streams by creating and awaiting futures in a loop. We unify the output
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; of both futures through the `Message` enum.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = stream::repeat_with(|| async { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_send&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; file, &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; channel).await }).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(Message::None);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = stream::repeat_with(|| async { socket.read_packet.await }).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(Message::Data);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Merge both the streams and wait for their output one-by-one.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; s = a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;merge&lt;&#x2F;span&gt;&lt;span&gt;(b);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(msg) = s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().await {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; msg {
&lt;&#x2F;span&gt;&lt;span&gt;        Message::None =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;continue&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        Message::Data(s) =&amp;gt;  ...,
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This creates an endlessly looping stream for sending data from the file into the
channel, and another endlessly looping stream to read data from the socket. It&#x27;s
definitely more verbose than the original &lt;code&gt;select! {}&lt;&#x2F;code&gt; example, but we also have 100%
less data loss. Instead of dropping and re-creating &lt;code&gt;read_send&lt;&#x2F;code&gt; each time
&lt;code&gt;read_packet&lt;&#x2F;code&gt; makes progress, both just keep moving forward the way you would
expect them to.&lt;&#x2F;p&gt;
&lt;p&gt;Would I write this for a project I&#x27;m working on? Probably not; I&#x27;d likely use
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-task-group&#x2F;latest&#x2F;async_task_group&#x2F;&quot;&gt;&lt;code&gt;async-task-group&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
instead. But I think this is helpful to show a practical example of a
well-publicized issue with &lt;code&gt;select! {}&lt;&#x2F;code&gt; and how &lt;code&gt;Stream::merge&lt;&#x2F;code&gt; would help guard
against that too.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fairness&quot;&gt;Fairness&lt;&#x2F;h2&gt;
&lt;p&gt;There is one issue with &lt;code&gt;merge&lt;&#x2F;code&gt; we haven&#x27;t covered yet: fairness. Let&#x27;s look at
the example which merges three streams into one:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = stream::repeat(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = stream::repeat(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = stream::repeat(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; d = stream::repeat(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; s = a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;merge&lt;&#x2F;span&gt;&lt;span&gt;(b).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;merge&lt;&#x2F;span&gt;&lt;span&gt;(c).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;merge&lt;&#x2F;span&gt;&lt;span&gt;(d);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Streams &lt;code&gt;a&lt;&#x2F;code&gt;, &lt;code&gt;b&lt;&#x2F;code&gt;, and &lt;code&gt;c&lt;&#x2F;code&gt; will yield a number exactly three times. Because they
always have an item available futures will always immediately yield the data
that they have, instead of breifly waiting. Which means that if we implement our
&lt;code&gt;merge&lt;&#x2F;code&gt; function without accounting for this, we would end up with:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;assert_eq!(s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span&gt;(), vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is not what we want: this has exactly the same semantics of
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;latest&#x2F;async_std&#x2F;stream&#x2F;trait.Stream.html#method.chain&quot;&gt;&lt;code&gt;Stream::chain&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, and will exhaust streams in-order. Ideally we&#x27;d like a random
mix of &lt;code&gt;1&lt;&#x2F;code&gt;s, &lt;code&gt;2&lt;&#x2F;code&gt;s, &lt;code&gt;3&lt;&#x2F;code&gt;s, and &lt;code&gt;4&lt;&#x2F;code&gt;s. In order to do that we need to randomly pick
between the items available from &lt;code&gt;merge.&lt;&#x2F;code&gt; Unfortunately because we&#x27;re merging
streams by chaining calls to &lt;code&gt;merge&lt;&#x2F;code&gt; we can only pick between two streams at a
time &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#at-a-time&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. This causes the chance we&#x27;ll pick an item from a stream to be skewed. For
the first 3 items in the stream, what we want is for each number to have exactly
a &lt;code&gt;25%&lt;&#x2F;code&gt; chance to be picked. But instead the chance we&#x27;ll get a number is
skewed as follows:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;number &lt;code&gt;1&lt;&#x2F;code&gt;: 50% chance&lt;&#x2F;li&gt;
&lt;li&gt;number &lt;code&gt;2&lt;&#x2F;code&gt;: 25% chance&lt;&#x2F;li&gt;
&lt;li&gt;number &lt;code&gt;3&lt;&#x2F;code&gt;: 12.5% chance&lt;&#x2F;li&gt;
&lt;li&gt;number &lt;code&gt;4&lt;&#x2F;code&gt;: 12.5% chance&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The way to fix this is by making &lt;code&gt;merge&lt;&#x2F;code&gt; aware of &lt;em&gt;all&lt;&#x2F;em&gt; streams we&#x27;re merging,
so we can pick fairly between them. We could do this either by creating a
&lt;code&gt;merge!&lt;&#x2F;code&gt; macro, or by doing what we chose to do in &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-concurrency&#x2F;latest&#x2F;futures_concurrency&#x2F;&quot;&gt;&lt;code&gt;futures-concurrency&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:
implement a trait for tuples [^merge-macro]. Here&#x27;s what using that looks like today:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;at-a-time&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;The reason for this is that when we call &lt;code&gt;a.merge(b)&lt;&#x2F;code&gt; the &lt;code&gt;merge&lt;&#x2F;code&gt;
function only knows about &lt;code&gt;a&lt;&#x2F;code&gt; and &lt;code&gt;b&lt;&#x2F;code&gt;. If &lt;code&gt;b&lt;&#x2F;code&gt; holds the stream produced by
&lt;code&gt;c.merge(d)&lt;&#x2F;code&gt;, then the probabilities divided between &lt;code&gt;a&lt;&#x2F;code&gt;, &lt;code&gt;b&lt;&#x2F;code&gt;, &lt;code&gt;c&lt;&#x2F;code&gt; are now
skewed. This is really annoying, and the only way we can resolve this is if we know
how many items we need to choose from &lt;em&gt;ahead of time&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = stream::repeat(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = stream::repeat(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = stream::repeat(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; d = stream::repeat(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; s = (a, b, c, d).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;merge&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will gives us exactly the probability we&#x27;re looking for, ensuring one
stream will not consistently be exhausted before another:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;number &lt;code&gt;1&lt;&#x2F;code&gt;: 25% chance&lt;&#x2F;li&gt;
&lt;li&gt;number &lt;code&gt;2&lt;&#x2F;code&gt;: 25% chance&lt;&#x2F;li&gt;
&lt;li&gt;number &lt;code&gt;3&lt;&#x2F;code&gt;: 25% chance&lt;&#x2F;li&gt;
&lt;li&gt;number &lt;code&gt;4&lt;&#x2F;code&gt;: 25% chance&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In past post&#x27;s we&#x27;ve discussed &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;future-join-and-const-eval&#x2F;&quot;&gt;the arity of the &lt;code&gt;join&lt;&#x2F;code&gt;
APIs&lt;&#x2F;a&gt; and its API
consequences at length. But we haven&#x27;t done so considering &lt;em&gt;fairness&lt;&#x2F;em&gt;
specifically. For the &lt;code&gt;join&lt;&#x2F;code&gt; family of APIs, it&#x27;s generally an all-or-nothing
approach, so fairness is as not much of an issue &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#error-path&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. But for &lt;code&gt;race&lt;&#x2F;code&gt;, which only
returns a single item, it might be. And so the same arguments we&#x27;re making here
in favor of a trait-based approach for &lt;code&gt;merge&lt;&#x2F;code&gt; apply to &lt;code&gt;race&lt;&#x2F;code&gt; as well.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;error-path&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;code&gt;Future::try_join&lt;&#x2F;code&gt; can return a single item when handling an
error, so fairness &lt;em&gt;could&lt;&#x2F;em&gt; be an issue. So it&#x27;s not an exact science. But I&#x27;m
not sure how important that is though. Maybe we just should account for it?&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;shiny-future&quot;&gt;Shiny Future&lt;&#x2F;h2&gt;
&lt;p&gt;Thinking about a future where we introduce &lt;code&gt;Stream::merge&lt;&#x2F;code&gt; (or &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;pull&#x2F;3208&quot;&gt;more likely&lt;&#x2F;a&gt;:
&lt;code&gt;AsyncIterator::merge&lt;&#x2F;code&gt;) into the stdlib paints a wholly different picture. It
already works well as-is. But as we add more features to the language that we
want anyway, using &lt;code&gt;Stream::merge&lt;&#x2F;code&gt; would in turn become nicer to use as well.
So let&#x27;s have fun shall we. What if Rust had &lt;em&gt;all&lt;&#x2F;em&gt; the language features, what could our code look like then?:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;async iteration so we can write async &lt;code&gt;for&lt;&#x2F;code&gt; loops&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;match&lt;&#x2F;code&gt; shorthands so we can reduce some of the nesting&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Merge&lt;&#x2F;code&gt; implemented directly on tuples.&lt;&#x2F;li&gt;
&lt;li&gt;an &lt;code&gt;IntoAsyncIterator&lt;&#x2F;code&gt; trait implemented in all the same places as &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; is&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;std::stream&lt;&#x2F;code&gt; renamed to &lt;code&gt;std::async_iter&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::async_iter;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The shared output type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;Message {
&lt;&#x2F;span&gt;&lt;span&gt;    Num(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    Text(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static str&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create our streams and map them to the shared output type.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_async_iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(Message::Num);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = [&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;chashu&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;nori&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;lily&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_async_iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(Message::Text);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = async_iter::once(async { &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; }).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(Message::Text);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Merge the streams, iterate over them, and handle the output sequentially.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; await msg in (a, b, c).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;merge&lt;&#x2F;span&gt;&lt;span&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    Num(n) =&amp;gt; println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;received a number: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{n}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;),
&lt;&#x2F;span&gt;&lt;span&gt;    Text(s) =&amp;gt; println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;received a string: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{s}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;),
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So far these features seem somewhat plausible: these are all features that are
fairly straight-forward syntactic sugar for existing patterns. And importantly:
none of these features are specific to the operations we&#x27;re doing here. Which
means that even if we&#x27;re looking at possible new language features here, none of
these are specific to async concurrency. But what if we
&lt;em&gt;really&lt;&#x2F;em&gt; took it further. Let&#x27;s dream big for a moment here. What if Rust also had:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-overloading&#x2F;&quot;&gt;&quot;async overloading&quot;&lt;&#x2F;a&gt; and an async overload for &lt;code&gt;IntoIter&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;async IntoIter&lt;&#x2F;code&gt; implemented for all &lt;code&gt;T: Future&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;issues&#x2F;294#issuecomment-761604444&quot;&gt;anonymous enums&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;type ascription in match statements&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create our streams and map them to the shared output type.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `into_iter` here assumes &amp;quot;async overloading&amp;quot;.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = [&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;chashu&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;nori&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;lily&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = async { &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; };
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Merge the streams, iterate over them, and handle the output sequentially.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `merge` expects `T: async IntoIter`, which all types implement, so it just works.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The type of `msg` here is `u8 | &amp;amp;str`. This is inferred from the input types
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; and represented in the match statement.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; await msg in (a, b, c).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;merge&lt;&#x2F;span&gt;&lt;span&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    n: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span&gt;=&amp;gt; println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;received a number: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{n}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;),
&lt;&#x2F;span&gt;&lt;span&gt;    s: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str &lt;&#x2F;span&gt;&lt;span&gt;=&amp;gt; println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;received a string: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{s}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;),
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I can&#x27;t say for sure whether this is a good idea or not. We&#x27;re actively investigating
if async overloading can work. And I have no clue if an async &lt;code&gt;Iterator for T where T: Future&lt;&#x2F;code&gt; blanket impl is a good idea. But the point of this
example is to have fun with it. To go big on the &quot;what if&quot;. Maybe none of these
features will ever land. But it&#x27;s still a useful exercise to understand to
which degree ergonomics are inherent of the API, and to which degree they&#x27;re
tied to other factors.&lt;&#x2F;p&gt;
&lt;p&gt;The future of Rust is what we make of it, so who knows if any of this will ever
happen. But even if it doesn&#x27;t: we&#x27;ve already shown that achieving this is
possible using today&#x27;s Rust. What we&#x27;re showing here is purely just to make it
so we need to write less code to achieve the same effect.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;addendum-ergonomics-explorations-for-operating-exclusively-on-futures&quot;&gt;Addendum: ergonomics explorations for operating exclusively on futures&lt;&#x2F;h2&gt;
&lt;p&gt;Hi, editor Yosh here. I&#x27;m adding this section close to the time I&#x27;d hit publish
on the post. My co-worker &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;nick_r_cameron&quot;&gt;nrc&lt;&#x2F;a&gt; helped review this post, and they asked me
whether I could show an example using futures exclusively.&lt;&#x2F;p&gt;
&lt;p&gt;We could directly implement &lt;code&gt;merge&lt;&#x2F;code&gt; on &lt;code&gt;Future&lt;&#x2F;code&gt;, creating a &lt;code&gt;Stream&lt;&#x2F;code&gt;, but that
wouldn&#x27;t lend itself well to chaining multiple futures: &lt;code&gt;a.merge(b).merge(c)&lt;&#x2F;code&gt;
first creates a stream from &lt;code&gt;a.merge(b)&lt;&#x2F;code&gt;, then tries to merge future &lt;code&gt;c&lt;&#x2F;code&gt; to it,
which won&#x27;t work.&lt;&#x2F;p&gt;
&lt;p&gt;Working around this problem requires implementing the &lt;code&gt;Merge&lt;&#x2F;code&gt; trait for &lt;code&gt;Future&lt;&#x2F;code&gt;
containers as well, which would not work on stable Rust today. We&#x27;d want to use
negative trait bounds to express the right bounds:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;impl [T; N] where N: IntoFuture + !IntoStream&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;impl [T; N] where N: IntoStream + !IntoFuture&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And even with these bounds, merging &lt;code&gt;Stream&lt;&#x2F;code&gt; and &lt;code&gt;Future&lt;&#x2F;code&gt; types would &lt;em&gt;still&lt;&#x2F;em&gt;
mean we&#x27;d require casting all futures to streams first. We could overcome this
by having a third trait, &lt;code&gt;IntoMergable&lt;&#x2F;code&gt; or something, and then making our
generic container impls rely on that:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;impl IntoMergable for T where T: IntoFuture + !IntoStream&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;impl IntoMergable for T where T: IntoStream + !IntoFuture&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;[T; N] where N: IntoMergable&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;But that doesn&#x27;t seem great. In general I think it&#x27;s worth assessing the
following considering ergonomics in this order:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;How often does &lt;code&gt;merge&lt;&#x2F;code&gt;-ing futures come up in practice?&lt;&#x2F;li&gt;
&lt;li&gt;Is that often enough that it would warrant changes to the language?&lt;&#x2F;li&gt;
&lt;li&gt;Would &lt;code&gt;impl IntoStream for T: IntoFuture&lt;&#x2F;code&gt; be a feasible?&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;As I mentioned in earlier examples, my intuition is that whenever we want to
&lt;code&gt;merge&lt;&#x2F;code&gt; futures, we likely could solve the problem more elegantly using
&lt;code&gt;task::spawn{,_local}&lt;&#x2F;code&gt;. Meaning if we design APIs such as
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-task-group&#x2F;latest&#x2F;async_task_group&#x2F;&quot;&gt;&lt;code&gt;TaskGroup&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; well,
we could carry &lt;code&gt;Stream::merge&lt;&#x2F;code&gt;-like semantics through this. In fact, that is
exactly what Swift&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;documentation&#x2F;swift&#x2F;taskgroup&quot;&gt;&lt;code&gt;TaskGroup&lt;&#x2F;code&gt;
type&lt;&#x2F;a&gt; does.
It can asynchronously iterate out all results from the group, allowing the
caller to handle them one-by-one.&lt;&#x2F;p&gt;
&lt;p&gt;So to summarize this side-adventure: if we&#x27;re looking to improve the semantics
of using &lt;code&gt;Stream::merge&lt;&#x2F;code&gt; using futures only, there are a fair number of
questions and avenues we should explore before we draw any definitive
conclusions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-async-rust-concurrency-tables-completed&quot;&gt;The async Rust concurrency tables: completed&lt;&#x2F;h2&gt;
&lt;p&gt;We can now begin filling in the original async Rust concurrency table using
&lt;code&gt;Stream::merge&lt;&#x2F;code&gt;. Because &lt;code&gt;Stream::merge&lt;&#x2F;code&gt; enables on items to be operated one at
the time, it can both &quot;continue on error&quot; and &quot;return early on error&quot;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; s = a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;merge&lt;&#x2F;span&gt;&lt;span&gt;(b);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; continue on error
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(item) in s {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; do something with `item`.
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; return early on error
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(item) in s {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; item = item?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; do something with `item`.
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This means &lt;code&gt;Stream::merge&lt;&#x2F;code&gt; allows you to choose from either short-circuiting behavior:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Wait for all outputs&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Wait for first output&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Handle output one-by-one&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Continue on error&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::join&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::try_race&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Stream::merge&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Return early on error&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::try_join&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::race&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Stream::merge&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Regarding our second table, &lt;code&gt;Stream::merge&lt;&#x2F;code&gt; enables the concurrency mode where
we &quot;handle all items&quot; and &quot;start responding on the first item&quot;. This is the
top-left of the table. But what about the case where we&#x27;re only interested in
the last item, and want to discard the rest? It turns out that that&#x27;s a subset
of the functionality exposed by &lt;code&gt;Stream::merge&lt;&#x2F;code&gt;, which we can get by using
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;latest&#x2F;async_std&#x2F;stream&#x2F;trait.Stream.html#method.last&quot;&gt;&lt;code&gt;Stream::last&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Handle all items&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Discard some items&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Response starts on first item&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Stream::merge&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::race&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Response starts on last item&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::join&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Stream::merge&lt;&#x2F;code&gt; + &lt;code&gt;Stream::last&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Seeing this table as it is, you might wonder what the difference is between e.g.
&lt;code&gt;Future::join&lt;&#x2F;code&gt; and &lt;code&gt;Stream::collect&lt;&#x2F;code&gt;. Or converting futures into streams and
then breaking on the first item. You&#x27;d be right: in theory we could model
everything using streams and call it a day. But in practice it wouldn&#x27;t feel good.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The reason why &lt;code&gt;Stream::merge&lt;&#x2F;code&gt; is the right answer for combining N futures is
because it allows us to express the time aspect of the operation&lt;&#x2F;strong&gt;. We don&#x27;t
want all or nothing. We want items, in any order, as soon as they&#x27;re made
available to us. &lt;strong&gt;Streams are &quot;data over time&quot;. And even if the data is
originally held in futures, the time aspect can only be expressed using
streams.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In contrast, the &lt;code&gt;Future::join&lt;&#x2F;code&gt; and &lt;code&gt;Future::race&lt;&#x2F;code&gt; family of operations do not
rely on the same time aspect. &lt;code&gt;join&lt;&#x2F;code&gt; yields all items.
&lt;code&gt;race&lt;&#x2F;code&gt; just yields the one. So converting futures via streams back to singular
items is an indirect mapping which ends up feeling clunky to author. And worse:
it creates opportunities to introduce bugs. &lt;code&gt;Future::join&lt;&#x2F;code&gt; and &lt;code&gt;Future::race&lt;&#x2F;code&gt;
may be subsets of &lt;code&gt;Stream::merge&lt;&#x2F;code&gt;, but they are unambiguous in what they
express which makes them a useful abstraction.&lt;&#x2F;p&gt;
&lt;p&gt;Overall this
We might still want to change the names of the concurrency combinators later on.
But the core functionality, shape, and usage all feels stable and consistent.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve looked at Rust&#x27;s 5th mode of concurrency: &quot;Await multiple
futures concurrently and operate on them as soon as they&#x27;re ready.&quot;
And in passing also covered the 6th mode of concurrency:
&quot;await multiple futures concurrently and discard all values but the last&quot;. We&#x27;ve
shown how this can be handled using the &lt;code&gt;futures::select!&lt;&#x2F;code&gt; macro. How this can
better be handled using &lt;code&gt;Stream::merge&lt;&#x2F;code&gt;. And talked about the various
considerations and future directions we have for this design.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ve also done a real-world case analysis of an accidental mis-use of the
&lt;code&gt;select!&lt;&#x2F;code&gt; macro, and shown how &lt;code&gt;Stream::merge&lt;&#x2F;code&gt; would&#x27;ve prevented the same issue
from happening by making the failure case unrepresentable. Overall
&lt;code&gt;Stream::merge&lt;&#x2F;code&gt; presents itself as a viable alternative to &lt;code&gt;select!&lt;&#x2F;code&gt; for the
&quot;handle one future at a time without ever discarding any&quot; model of concurrency.&lt;&#x2F;p&gt;
&lt;p&gt;Overall I&#x27;m incredibly pleased with the progress we&#x27;ve made with this series.
After nearly three years of work we finally have documented all modes of
concurrency for async Rust, and their corresponding interfaces. We can now start
experimenting with naming, polish, documentation, and then possibly (finally!)
start bringing some of these things into mainline Rust via RFCs. Things will
likely change between now and then, but it&#x27;s good to finally stop needing to
think about semantics, and being able to focus more on ergonomics. It&#x27;s been a
slow process, but I&#x27;m incredibly happy with the outcome. And thank you for
following along over all of these years!&lt;&#x2F;p&gt;
&lt;p&gt;If you liked this post and would like to see my cats, you can &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;yoshuawuyts&quot;&gt;follow me on
Twitter&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Thanks to: &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;ryan_levick&quot;&gt;Ryan Levick&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;nick_r_cameron&quot;&gt;Nick Cameron&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;_lrlna&quot;&gt;Irina Shestak&lt;&#x2F;a&gt; for reviewing drafts of this post.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;appendix-async-rust-concurrency-operations&quot;&gt;Appendix: Async Rust Concurrency Operations&lt;&#x2F;h2&gt;
&lt;p&gt;These are all the concurrency operations we want to be able to express in async
Rust.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;1-concurrency-adapters-by-fallibility-mode-and-output-handling&quot;&gt;1. Concurrency adapters by fallibility mode and output handling&lt;&#x2F;h4&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Wait for all outputs&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Wait for first output&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Handle output one-by-one&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Continue on error&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::join&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::try_race&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Stream::merge&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Return early on error&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::try_join&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::race&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Stream::merge&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h4 id=&quot;2-concurrency-adapters-by-response-start-and-output-handling&quot;&gt;2. Concurrency adapters by response start and output handling&lt;&#x2F;h4&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Handle all items&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Discard some items&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Response starts on first item&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Stream::merge&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::race&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Response starts on last item&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::join&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Stream::merge&lt;&#x2F;code&gt; + &lt;code&gt;Stream::last&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
</description>
        </item>
        <item>
            <title>Uninit Read&#x2F;Write</title>
            <pubDate>Tue, 07 Dec 2021 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/uninit-read-write/</link>
            <guid>https://blog.yoshuawuyts.com/uninit-read-write/</guid>
            <description>&lt;p&gt;The &lt;code&gt;AsyncRead&lt;&#x2F;code&gt; and &lt;code&gt;AsyncWrite&lt;&#x2F;code&gt; traits are async versions of the &lt;code&gt;Read&lt;&#x2F;code&gt; and
&lt;code&gt;Write&lt;&#x2F;code&gt; traits in Rust. They&#x27;re core to async Rust, providing the interface to
read and write bytes from for example the filesystem and network. But both the
async and non-async variants have an open issue: how can we use these traits to
write data into uninitialized memory?&lt;&#x2F;p&gt;
&lt;p&gt;In this post we look at the problem of reading into unitialized memory using
&lt;code&gt;Read&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;Write&lt;&#x2F;code&gt;, and at possible solution we could introduce to solve this.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;showing-the-problem&quot;&gt;Showing the problem&lt;&#x2F;h2&gt;
&lt;p&gt;Both async and non-async Rust share the same issue for both &lt;code&gt;Read&lt;&#x2F;code&gt; and &lt;code&gt;Write&lt;&#x2F;code&gt;
traits. So let&#x27;s take use the non-async &lt;code&gt;Read&lt;&#x2F;code&gt; trait as our example. It&#x27;s
defined as follows:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Read {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Calling &lt;code&gt;Read::read&lt;&#x2F;code&gt; will read bytes into a mutable slice of memory, and return
an &lt;code&gt;io::Result&lt;&#x2F;code&gt; containing either the number of bytes read, or an error. Usage
typically is something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; open a file and init the buffer
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; f = File::open(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;foo.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; buffer = vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1024&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; read up to 1024 bytes
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; read = f.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; buffer)?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; data = buffer[..read];
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will read 1024 bytes of the file into the buffer. But it comes with a slight
inefficiency: we&#x27;re writing zeroes into the buffer, and then immediately writing
more data into the buffer after that. This means &lt;strong&gt;we&#x27;re doing a double-write,
which is not as efficient as it could be&lt;&#x2F;strong&gt;
(&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;blob&#x2F;master&#x2F;text&#x2F;2930-read-buf.md#why-not-just-initialize&quot;&gt;report&lt;&#x2F;a&gt;).
Ideally we&#x27;d be able to do the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; open a file and init the buffer
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; f = File::open(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;foo.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; buf = Vec::with_capacity(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1024&lt;&#x2F;span&gt;&lt;span&gt;); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; reserve capacity, but don&amp;#39;t initialize
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; read up to 1024 bytes
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; read = f.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; buf)?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; data = buffer[..read];
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But this doesn&#x27;t work. Even if the &lt;em&gt;capacity&lt;&#x2F;em&gt; is 1024, because we
haven&#x27;t initialized the vector it&#x27;s as if we passed an empty slice, and the
following assertion will always hold:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;assert_eq!(data.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And this is the problem this post is about: our slices can&#x27;t have uninitialized
memory, and our vectors which &lt;em&gt;can&lt;&#x2F;em&gt; have uninitialized memory are always
dereferenced into slices first. In order to support writing into uninitialized
memory over &lt;code&gt;Read&lt;&#x2F;code&gt; bounds we need to resolve this.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;solution-1-unitialized-slices&quot;&gt;Solution 1: unitialized slices&lt;&#x2F;h2&gt;
&lt;p&gt;The current thinking is that we can solve this issue by introducing &quot;slices of
unitialized memory&quot; and extending the IO traits with methods dedicated to taking
these slices. This was proposed and subsequently merged as part of &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;blob&#x2F;master&#x2F;text&#x2F;2930-read-buf.md&quot;&gt;RFC
2930: read_buf&lt;&#x2F;a&gt;
(&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;78485&quot;&gt;tracking issue&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;The RFC is worth a read if you want a closer look at the problem space. But the
gist of the solution it proposes is as follows:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Add a new &lt;code&gt;ReadBuf&lt;&#x2F;code&gt; type which wraps &lt;code&gt;[MaybeUninit::&amp;lt;u8&amp;gt;::uninit(); N];&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Add an optional &lt;code&gt;read_buf&lt;&#x2F;code&gt; method which takes &lt;code&gt;&amp;amp;mut ReadBuf&amp;lt;&#x27;_&amp;gt;&lt;&#x2F;code&gt;
instead of &lt;code&gt;&amp;amp;mut [u8]&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Users who want to read into uninitialized memory can implement and use
&lt;code&gt;read_buf&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The RFC provides the following usage example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; buf = [MaybeUninit::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;::uninit(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;8192&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; buf = ReadBuf::uninit(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; buf);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    some_reader.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_buf&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; buf)?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; buf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;filled&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_empty&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;process_data&lt;&#x2F;span&gt;&lt;span&gt;(buf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;filled&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;    buf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;clear&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With the following definition for &lt;code&gt;Read::read_buf&lt;&#x2F;code&gt; provided by default, intended
to be modified by implementers:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Read &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;MyReader {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read_buf&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;ReadBuf&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; io::Result&amp;lt;()&amp;gt; { 
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; n = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(buf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;initialize_unfilled&lt;&#x2F;span&gt;&lt;span&gt;())?;
&lt;&#x2F;span&gt;&lt;span&gt;        buf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add_filled&lt;&#x2F;span&gt;&lt;span&gt;(n);
&lt;&#x2F;span&gt;&lt;span&gt;        Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This achieves the goal it sets out to do: we successfully can read data into
uninitialized memory. However for users it requires a little more work to setup:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Read into uninit memory.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; buf = [MaybeUninit::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;::uninit(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1024&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; buf = ReadBuf::uninit(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; buf);
&lt;&#x2F;span&gt;&lt;span&gt;file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_buf&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; buf)?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; data = buf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;filled&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Read into init memory
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; buf = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1024&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; read = file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; buf)?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; data = buf[..read];
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Overall this is not too bad, and gets us in the right direction. In order to
write bytes to the heap instead of the stack I believe you can wrap the buf in a
&lt;code&gt;Box::new&lt;&#x2F;code&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#placement-new&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#vec-uninit&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. The main downsides are that it requires using
a dedicated type just for this purpose, and it&#x27;s slightly more verbose.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;placement-new&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;I believe with placement new (&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;src&#x2F;alloc&#x2F;boxed.rs.html#191&quot;&gt;&lt;code&gt;box&lt;&#x2F;code&gt;
keyword&lt;&#x2F;a&gt;) this might save
yet another copy.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;vec-uninit&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Or as &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;maybewaffle&#x2F;status&#x2F;1468579107730513921&quot;&gt;maybewaffle pointed
out&lt;&#x2F;a&gt;: this could be
used with &lt;code&gt;Vec::spare_capacity_mut&lt;&#x2F;code&gt; as well.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;solution-2-uninitialized-vectors&quot;&gt;Solution 2: uninitialized vectors&lt;&#x2F;h2&gt;
&lt;p&gt;Since August 2020, the
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nightly&#x2F;std&#x2F;vec&#x2F;struct.Vec.html#method.spare_capacity_mut&quot;&gt;&lt;code&gt;Vec::spare_capacity_mut&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
method has been available on nightly. This returns the remaining spare capacity
of the vector as a slice of &lt;code&gt;MaybeUninit&amp;lt;T&amp;gt;&lt;&#x2F;code&gt;. The docs show the following usage
example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; v = Vec::with_capacity(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; uninit = v.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spare_capacity_mut&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;uninit[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;uninit[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;uninit[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Mark the first 3 elements of the vector as being initialized.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    v.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;set_len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(&amp;amp;v, &amp;amp;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This API fills much the same role as the &lt;code&gt;ReadBuf&lt;&#x2F;code&gt; type did in the first
solution, but without requiring a new type to be introduced. Usage of
uninitialized vectors becomes a lot closer to the current &lt;code&gt;Read::read&lt;&#x2F;code&gt; behavior:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Read into uninit memory.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; buf = Vec::with_capacity(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1024&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; read = file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_buf&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; buf)?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; data = buf[..read];
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Read into init memory
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; buf = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1024&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; read = file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; buf)?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; data = buf[..read];
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Implementers of &quot;leaf&quot; IO types (e.g. &lt;code&gt;File&lt;&#x2F;code&gt;, etc.) could use this method to
implement a reader which reads directly into uninitialized memory. The default
implementation of &lt;code&gt;read_buf&lt;&#x2F;code&gt; could become something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Read &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;MyReader {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read_buf&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Vec&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) -&amp;gt; io::Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; { 
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; zero-fill the unintialized memory
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; uninit = buf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spare_capacity_mut&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        mem::swap(uninit, &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;MaybeUninit::zeroed());
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ buf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;set_len&lt;&#x2F;span&gt;&lt;span&gt;(buf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;capacity&lt;&#x2F;span&gt;&lt;span&gt;()) };
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; read the data into the buffer
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(buf)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s worth pointing out that the name &lt;code&gt;read_buf&lt;&#x2F;code&gt; at this point doesn&#x27;t convey
the intent particularly well anymore. A name such as &lt;code&gt;read_to_capacity&lt;&#x2F;code&gt; might
more closely match our intent. To my knowledge: &lt;em&gt;&quot;Read into the uninitialized
bytes of a &lt;code&gt;Vec&lt;&#x2F;code&gt;, but don&#x27;t grow beyond it&quot;&lt;&#x2F;em&gt;, doesn&#x27;t have any precedent in the
stdlib. The closest I can think of is &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;vec&#x2F;struct.Vec.html#method.fill&quot;&gt;&lt;code&gt;Vec::fill&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;,
but it&#x27;s not quite it. If we choose to use this API, method naming and
documentation is something we should take a more closer look at.&lt;&#x2F;p&gt;
&lt;p&gt;Even reading into the stack becomes possible if we use
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nightly&#x2F;std&#x2F;vec&#x2F;struct.Vec.html#method.with_capacity_in&quot;&gt;&lt;code&gt;Vec::with_capacity_in&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
backed by a stack allocator. The ergonomics of that aren&#x27;t ideal yet, but that&#x27;s
expected to significantly improve over time &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#hype&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;hype&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;I know folks are actively looking at the ergonomics of this, and am
excited for some of the designs I&#x27;ve seen.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;As we mentioned, the main benefit of this approach is that it doesn&#x27;t introduce
a new type and as such maps nicely to existing patterns. Compared to the first
solution we have better ergonomics when reading into the heap, and slightly
worse ergonomics when reading into the stack. Overall I think this approach is
promising, and I prefer it over the first solution.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;solution-3-specialization&quot;&gt;Solution 3: specialization&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Disclaimer: I&#x27;m by no stretch an authority on dynamic dispatch or
specialization. It might be that I got details wrong, or misunderstood
limitations. This section is &quot;best effort&quot;, and am happy to update it if turns
out I got something wrong.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Going back to our earlier example, an ideal solution would be if instead of
defining a new &lt;code&gt;read_buf&lt;&#x2F;code&gt; methods we could keep using the &lt;code&gt;read&lt;&#x2F;code&gt; method instead:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Read into uninit memory.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; buf = Vec::with_capacity(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1024&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; read = file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; buf)?; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; note: `read`, not `read_buf`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; data = buf[..read];
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The way to do this in Rust would be using &lt;em&gt;specialization&lt;&#x2F;em&gt;. Specialization is
still considered &quot;unstable&quot;, and has not yet been fully formed. So don&#x27;t expect
the code below to work anytime soon, if ever. But if we squint a little, we
could imagine a trait could be defined as follows:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Read {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The &amp;quot;default&amp;quot; implementation.
&lt;&#x2F;span&gt;&lt;span&gt;    default &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Implementation specialized for `&amp;amp;mut Vec&amp;lt;u8&amp;gt;`
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Vec&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; zero-fill the unintialized memory
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; uninit = buf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spare_capacity_mut&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        mem::swap(uninit, &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;MaybeUninit::zeroed());
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ buf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;set_len&lt;&#x2F;span&gt;&lt;span&gt;(buf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;capacity&lt;&#x2F;span&gt;&lt;span&gt;()) };
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; read the data into the buffer
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(buf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_slice&lt;&#x2F;span&gt;&lt;span&gt;())
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this example we define the trait &lt;code&gt;Read&lt;&#x2F;code&gt; with a &quot;default&quot; implementation for
&lt;code&gt;&amp;amp;mut [u8]&lt;&#x2F;code&gt;, and a built-in specialization for &lt;code&gt;&amp;amp;mut Vec&amp;lt;u8&amp;gt;&lt;&#x2F;code&gt;. The
specialization needs to be built directly into the trait definition, to ensure
that &lt;code&gt;&amp;amp;mut Vec&amp;lt;u8&amp;gt;&lt;&#x2F;code&gt; will never default to being interpreted as an zero-length
slice. Trait implementers would be expected to provide their own specialization
for &lt;code&gt;&amp;amp;mut Vec&amp;lt;u8&amp;gt;&lt;&#x2F;code&gt;, to make use of the ability to write directly into
uninitialized memory.&lt;&#x2F;p&gt;
&lt;p&gt;Another thing that&#x27;s unclear about specializations is the interactions with
semver. In our example we&#x27;re now using &lt;code&gt;Vec::capacity&lt;&#x2F;code&gt; rather than &lt;code&gt;Vec::len&lt;&#x2F;code&gt; to
determine how many bytes to write into the vector. All observable changes in
behavior have &lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;1172&#x2F;&quot;&gt;the potential to be breaking&lt;&#x2F;a&gt;, so any
modification to this behavior should always use crater to determine impact. But
it doesn&#x27;t seem like we would break any intended use of the APIs.&lt;&#x2F;p&gt;
&lt;p&gt;At first glance this interface might seem ideal. It&#x27;s the same
interface that &lt;em&gt;just works&lt;&#x2F;em&gt; depending on what&#x27;s passed. But as remarked in
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;blob&#x2F;master&#x2F;text&#x2F;2930-read-buf.md&quot;&gt;RFC 2930: read_buf&lt;&#x2F;a&gt;,
this approach has issues:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;It must be compatible with dyn Read. Trait objects are used pervasively in
IO code, so a solution can&#x27;t depend on monomorphization or specialization.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Further elaboration on this point exists in &lt;a href=&quot;https:&#x2F;&#x2F;paper.dropbox.com&#x2F;doc&#x2F;IO-Buffer-Initialization--BXhgeuRHTIAB_zPZU52_DJo2Ag-MvytTgjIOTNpJAS6Mvw38&quot;&gt;this
document&lt;&#x2F;a&gt;
and
&lt;a href=&quot;http:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2020&#x2F;01&#x2F;20&#x2F;async-interview-5-steven-fackler&#x2F;#possible-solution-to-read-take-a-trait-object-and-not-a-buffer&quot;&gt;this interview&lt;&#x2F;a&gt;.
My interpretation of these materials is: &quot;Specialization is not dyn safe, so if
we add a specialization &lt;code&gt;dyn Read&lt;&#x2F;code&gt; would no longer be possible&quot;. That would mean
the if &lt;code&gt;Read&lt;&#x2F;code&gt; specialized as we showed, the following code would fail to
compile:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; This alias would cause an error because `Read` is not dyn safe.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;MyType = Box&amp;lt;dyn Read&amp;gt;;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Intuitively I would&#x27;ve expected this to be possible if we wanted it to, even if
it&#x27;s currently not implemented in the compiler. But my understanding of &lt;code&gt;dyn&lt;&#x2F;code&gt; is
limited compared to the folks who&#x27;ve written the docs, so I trust there are good
reasons why they marked it as a non-option.&lt;&#x2F;p&gt;
&lt;p&gt;That said though; the constraints around &lt;code&gt;dyn&lt;&#x2F;code&gt; in Rust are currently being
reworked in order to enable things like an &lt;code&gt;AsyncIterator&lt;&#x2F;code&gt; with &lt;a href=&quot;https:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;&#x2F;blog&#x2F;2021&#x2F;10&#x2F;15&#x2F;dyn-async-traits-part-6&#x2F;&quot;&gt;&lt;code&gt;async fn next&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
to work. Which makes me wonder: is the interaction between &lt;code&gt;dyn&lt;&#x2F;code&gt; and
specialization something which can be reworked as well?&lt;&#x2F;p&gt;
&lt;p&gt;I asked my colleague &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;tartanllama&quot;&gt;Sy&lt;&#x2F;a&gt; whether combining
dynamic dispatch with specialization is possible in C++, and it appears it is!
They walked me through &lt;a href=&quot;https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;zKcss4sd6&quot;&gt;this C++ example&lt;&#x2F;a&gt; which
combines a dynamic dispatch based on the class it&#x27;s called on and whether a
&lt;code&gt;vec&lt;&#x2F;code&gt; or &lt;code&gt;span&lt;&#x2F;code&gt; (slice) is passed. Even though the code is very different from
Rust, the functionality matches how we would expect it to work.&lt;&#x2F;p&gt;
&lt;p&gt;If we think about the wider implications of this, it seems &lt;em&gt;not great&lt;&#x2F;em&gt; if
specializations and dynamic dispatch would inherently remain mutually exclusive.
Both are incredibly useful, and if they can&#x27;t be used together that seems
incredibly limiting.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve shown three examples for reading into uninitialized memory in
Rust. As I mentioned throughout the post: it&#x27;d be great if we could make reading
into unitialized memory as close as possible to reading into initialized memory.
And I think in particular the second, and third examples have a lot of potential.&lt;&#x2F;p&gt;
&lt;p&gt;I was motivated to write this post after conversations with
&lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;nick_r_cameron&quot;&gt;nrc&lt;&#x2F;a&gt; last week. I remembered reading
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;amanieu&quot;&gt;Amanieu&#x27;s&lt;&#x2F;a&gt; comment about &lt;code&gt;spare_capacity_mut&lt;&#x2F;code&gt; on
the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;78485#issuecomment-828811458&quot;&gt;tracking issue for RFC 2930&lt;&#x2F;a&gt;,
and started thinking of what it could look like if we used that instead of
&lt;code&gt;ReadBuf&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In terms of timelines, I don&#x27;t believe we&#x27;re under great pressure to land the
features described in this post into the stdlib. The performance benefits can be
significant under certain workloads; but as we&#x27;re collectively moving towards
completion-based IO, traits such as
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-io&#x2F;latest&#x2F;futures_io&#x2F;trait.AsyncBufRead.html&quot;&gt;&lt;code&gt;AsyncBufRead&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
will &lt;a href=&quot;https:&#x2F;&#x2F;without.boats&#x2F;blog&#x2F;io-uring&#x2F;#copying-buffers-and-io-traits&quot;&gt;become more relevant&lt;&#x2F;a&gt;.
Because these traits manage buffers internally, uninitialized memory never needs
to cross trait boundaries and this post doesn&#x27;t apply.&lt;&#x2F;p&gt;
&lt;p&gt;I hope I was able to provide some insight on how we can enable reading into
uninitialized memory for (async) IO traits. If you liked this post and would
like to see my cats, you can &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;yoshuawuyts&quot;&gt;follow me on Twitter&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;tartanllama&quot;&gt;Sy Brand&lt;&#x2F;a&gt; for showing me how
dynamic dispatch and specialization interact in C++, and
&lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;nick_r_cameron&quot;&gt;nrc&lt;&#x2F;a&gt; for helping review this post.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Async Cancellation I</title>
            <pubDate>Wed, 10 Nov 2021 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/async-cancellation-1/</link>
            <guid>https://blog.yoshuawuyts.com/async-cancellation-1/</guid>
            <description>&lt;p&gt;Sometimes we start things but decide midway through that we would prefer to
rather not be doing them. That process is sometimes referred to as cancellation.
Say we accidentally clicked &quot;download&quot; on a large file in the browser. We should
have a way to tell the computer to stop downloading it.&lt;&#x2F;p&gt;
&lt;p&gt;When the async foundations WG was &lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;wg-async-foundations&#x2F;vision&#x2F;submitted_stories&#x2F;status_quo.html&quot;&gt;researching user stories&lt;&#x2F;a&gt;
earlier this year, async cancellation came up repeatedly. It&#x27;s one of those
things that&#x27;s important to have, but can be tricky to reason about. This is not
helped by the fact that little has been written about it, so I figured I might
try to make a dent in that by writing a deep-dive on the topic.&lt;&#x2F;p&gt;
&lt;p&gt;In this post we&#x27;ll look at async Rust&#x27;s async primitives, and cover how
cancellation works for those primitives today. We&#x27;ll then proceed to look at
ways in which we can ensure we do not end up with dangling resources. And
finally we&#x27;ll take a look at what the current direction of async Rust means for
async cancellation. Sounds like a plan? Good, let&#x27;s dive in!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tasks-and-futures&quot;&gt;Tasks and Futures&lt;&#x2F;h2&gt;
&lt;p&gt;For the purpose of this post we need to distinguish between two types of async
primitives in Rust: futures and tasks &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#stream&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;stream&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Arguably &quot;Stream&quot; &#x2F; &quot;AsyncIterator&quot; is a third async primitive, but
everything we say about the &lt;code&gt;Future&lt;&#x2F;code&gt; type applies to &lt;code&gt;Stream&lt;&#x2F;code&gt; as well, so we&#x27;re
considering those the same in this post.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Futures&lt;&#x2F;strong&gt; represent the core building block of async Rust, and exist as
part of the Rust language and stdlib. A future is something that when &lt;code&gt;.await&lt;&#x2F;code&gt;ed
becomes a value &lt;em&gt;later&lt;&#x2F;em&gt;. By design it does nothing unless &lt;code&gt;.await&lt;&#x2F;code&gt;ed, and must
be driven to completion by some other, external loop (&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;task&#x2F;trait.Wake.html#examples&quot;&gt;example of such a
loop&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tasks&lt;&#x2F;strong&gt; are not yet part of the Rust language or stdlib, and represent a
managed &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#managed&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; piece of async execution backed by an asynchronous
runtime &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#threads-analogy&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Tasks often allow for async code to become
multi-threaded: it&#x27;s common for executors to schedule tasks across multiple
threads, and even move them between threads after they&#x27;ve started executing. A
task does not need to be &lt;code&gt;.await&lt;&#x2F;code&gt;ed before it starts executing, and the future
it returns is just a way to get the return value of the task once it finishes.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;managed&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;&quot;managed&quot; is used throughout this post as: &quot;is scheduled on a
runtime&quot;. This typically comes with the requirement futures are &lt;code&gt;&#x27;static&lt;&#x2F;code&gt; (the
future does not hold any borrows), and when scheduled on a multi-threaded
runtime often, but not always, requires futures be &lt;code&gt;Send&lt;&#x2F;code&gt; as well (the future is
thread-safe).&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;threads-analogy&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;You can think of Tasks as being something akin to
lightweight threads, managed by your program rather than you operating system.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Many languages, including JavaScript, use equivalents to Rust tasks rather than
Rust futures as their core building blocks &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#equiv&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. This is convenient because
only a single type of async building block is exposed, and the language runtime
optimizers can figure out how to speed things up if needed. But in Rust we
unfortunately can&#x27;t rely on that, so we manually distinguish between unmanaged
(futures) and managed (tasks) primitives.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;equiv&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;JavaScript&#x27;s counterpart to Rust&#x27;s tasks is
&lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;JavaScript&#x2F;Reference&#x2F;Global_Objects&#x2F;Promise&quot;&gt;&lt;code&gt;Promise&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
It starts being executed the moment it&#x27;s instantiated, rather than the moment
it&#x27;s &lt;code&gt;await&lt;&#x2F;code&gt;ed. My understanding is that &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;dotnet&#x2F;csharp&#x2F;programming-guide&#x2F;concepts&#x2F;async&#x2F;#composition-with-tasks&quot;&gt;C#&#x27;s
&lt;code&gt;Task&amp;lt;T&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
works much the same way.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;cancelling-futures&quot;&gt;Cancelling Futures&lt;&#x2F;h2&gt;
&lt;p&gt;Cancellation allows for a future to stop doing work early, when we know we&#x27;re no
longer interested in its result. Futures in Rust can be &lt;em&gt;cancelled&lt;&#x2F;em&gt; at one of
two points. For simplicity most our examples in this post are going to use
sleeping and printing operations; where in the real world we&#x27;d probably be
talking about file&#x2F;network operations and data processing instead.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;1. Cancel a future before it starts executing&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Here we create a drop guard, pass it to an async function which returns a
future, and then drop the future before we &lt;code&gt;.await&lt;&#x2F;code&gt; it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::time::Duration;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Guard;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Drop &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Guard {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;guard&lt;&#x2F;span&gt;&lt;span&gt;: Guard) {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    task::sleep(Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)).await;
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; guard = Guard {};
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; fut = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;(guard);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;(fut);
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;done&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This prints:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;&amp;gt; 1
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; 2
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; done
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Our &lt;code&gt;Guard&lt;&#x2F;code&gt; type here will print when its
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;ops&#x2F;trait.Drop.html&quot;&gt;destructor (&lt;code&gt;Drop&lt;&#x2F;code&gt;)&lt;&#x2F;a&gt; is run.
We never actually execute the future, but the destructor is still run because we
passed the value to the async function. This means the first cancellation point
of any future is immediately after instantiation before the async functions&#x27;s
body has run. Meaning not all cancellation points are necessarily demarked by
&lt;code&gt;.await&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;2. Cancel a future at an await point&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Here we create a future, poll it exactly once, and then drop it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::{ptr, task};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::task;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::time::Duration;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    task::sleep(Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)).await;
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; fut = Box::pin(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; cx = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;empty_cx&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;assert!(fut.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; cx).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_pending&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;(fut);
&lt;&#x2F;span&gt;&lt;span&gt;println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;done&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Create an empty &amp;quot;Waker&amp;quot; callback, wrapped in a &amp;quot;Context&amp;quot; structure.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; How this works is not particularly important for the rest of this post.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;empty_cx&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; task::Context { ... }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;&amp;gt; 1
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; 2
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; done
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Fundamentally, you can think of &lt;strong&gt;&lt;code&gt;.await&lt;&#x2F;code&gt; as marking a point where
cancellation may occur.&lt;&#x2F;strong&gt; Where keywords like &lt;code&gt;return&lt;&#x2F;code&gt; and &lt;code&gt;?&lt;&#x2F;code&gt; mark points where
the function may return a value, &lt;code&gt;.await&lt;&#x2F;code&gt; marks a location where the function&#x27;s
caller may decide the function should not run any further. But importantly: in
all cases destructors will be run, allowing resources to be cleaned up.&lt;&#x2F;p&gt;
&lt;p&gt;Futures cannot be cancelled in between &lt;code&gt;.await&lt;&#x2F;code&gt; calls, or after the last
&lt;code&gt;.await&lt;&#x2F;code&gt; call. We also don&#x27;t yet have a design for &quot;async &lt;code&gt;Drop&lt;&#x2F;code&gt;&quot; so we also
can&#x27;t say anything meaningful yet about how how that will interact with
cancellation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cancelling-tasks&quot;&gt;Cancelling Tasks&lt;&#x2F;h2&gt;
&lt;p&gt;Because tasks aren&#x27;t standardized in Rust yet, cancellation of tasks isn&#x27;t
either. And unsurprisingly different runtimes have different ideas on how to
cancel a task. Both &lt;code&gt;async-std&lt;&#x2F;code&gt; and &lt;code&gt;tokio&lt;&#x2F;code&gt; share a similar task model.
I&#x27;m most comfortable with &lt;code&gt;async-std&lt;&#x2F;code&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#author&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, so let&#x27;s use that as an
example:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;author&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;Probably because I co-authored the project.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::task;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; handle = task::spawn(async {
&lt;&#x2F;span&gt;&lt;span&gt;    task::sleep(Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)).await;
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;(handle);     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Drop the task handle.
&lt;&#x2F;span&gt;&lt;span&gt;task::sleep(Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)).await;
&lt;&#x2F;span&gt;&lt;span&gt;println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;done&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;&amp;gt; 1
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; 2
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; done
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here we dropped the handle, but the task continued to run in the background.
This is because the &lt;code&gt;async-std&lt;&#x2F;code&gt; runtime uses &quot;detach on drop&quot; semantics for
tasks. This is the same in the &lt;code&gt;tokio&lt;&#x2F;code&gt; runtime. In order to cancel a task, we
need to manually call a method on the handle. For &lt;code&gt;async-std&lt;&#x2F;code&gt; this is
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.10.0&#x2F;async_std&#x2F;task&#x2F;struct.JoinHandle.html#method.cancel&quot;&gt;&lt;code&gt;JoinHandle::cancel&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;,
and for &lt;code&gt;tokio&lt;&#x2F;code&gt; this is
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio&#x2F;1.12.0&#x2F;tokio&#x2F;task&#x2F;struct.JoinHandle.html#method.abort&quot;&gt;&lt;code&gt;JoinHandle::abort&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::task;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; handle = task::spawn(async {
&lt;&#x2F;span&gt;&lt;span&gt;    task::sleep(Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)).await;
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;handle.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;cancel&lt;&#x2F;span&gt;&lt;span&gt;().await;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Cancel the task handle
&lt;&#x2F;span&gt;&lt;span&gt;task::sleep(Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)).await;
&lt;&#x2F;span&gt;&lt;span&gt;println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;done&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;&amp;gt; 1
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; done
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can see that if we call &lt;code&gt;JoinHandle::cancel&lt;&#x2F;code&gt;, the task is cancelled at that
point, and the number &lt;code&gt;2&lt;&#x2F;code&gt; is no longer printed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;propagating-cancellation-for-futures&quot;&gt;Propagating cancellation for futures&lt;&#x2F;h2&gt;
&lt;p&gt;In Async Rust cancellation automatically propagates for futures. When we stop
polling a future, all futures contained within will in turn also stop making
forward progress. And all
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;ops&#x2F;trait.Drop.html&quot;&gt;destructors&lt;&#x2F;a&gt; within them
will be run. In this example we&#x27;ll be using the
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.10.0&#x2F;async_std&#x2F;future&#x2F;fn.timeout.html&quot;&gt;&lt;code&gt;FutureExt::timeout&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
function from &lt;code&gt;async-std&lt;&#x2F;code&gt;, which returns a &lt;code&gt;Result&amp;lt;T, TimeoutError&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::task;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::time::Duration;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;timeout&lt;&#x2F;span&gt;&lt;span&gt;(Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;)).await;
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    task::sleep(Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)).await;
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;timeout&lt;&#x2F;span&gt;&lt;span&gt;(Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)).await;
&lt;&#x2F;span&gt;&lt;span&gt;println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;done&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;&amp;gt; 1
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; 2
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; 3
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; done    # `4` and `5` are never printed
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The tree of futures above can be expressed as the following graph:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;main
&lt;&#x2F;span&gt;&lt;span&gt;  -&amp;gt; foo (times out after 1 sec)
&lt;&#x2F;span&gt;&lt;span&gt;    -&amp;gt; bar (times out after 3 secs)
&lt;&#x2F;span&gt;&lt;span&gt;      -&amp;gt; task::sleep (wait for 2 secs)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Because &lt;code&gt;foo&lt;&#x2F;code&gt; is timed out and dropped before &lt;code&gt;bar&lt;&#x2F;code&gt; has the chance to complete,
not all numbers get to be printed. &lt;code&gt;bar&lt;&#x2F;code&gt; is dropped before it has the opportunity
to complete, and all of its resources are cleaned up when its destructors run.&lt;&#x2F;p&gt;
&lt;p&gt;This means that in order to cancel a chain of future, all we need to do is to
&lt;em&gt;drop it&lt;&#x2F;em&gt;, and all resources will in turn be cleaned up. Whether we&#x27;re dropping
a future by hand,
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.10.0&#x2F;async_std&#x2F;future&#x2F;fn.timeout.html&quot;&gt;calling a timeout method&lt;&#x2F;a&gt;
on a future, or
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;futures-concurrency-2&#x2F;&quot;&gt;racing multiple futures&lt;&#x2F;a&gt;
— cancellation will propagate, and resources will be cleaned up.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;propagating-cancellation-for-tasks&quot;&gt;Propagating cancellation for tasks&lt;&#x2F;h2&gt;
&lt;p&gt;As we showed earlier, simply dropping a task handle is not enough to cancel a
task in most runtimes. We need to explicitly invoke a cancellation method to
cancel the task. This means tasks aren&#x27;t automatically propagated.&lt;&#x2F;p&gt;
&lt;p&gt;In hindsight this was probably a mistake. More specifically, this was likely
&lt;em&gt;my&lt;&#x2F;em&gt; mistake. &lt;code&gt;async-std&lt;&#x2F;code&gt;&#x27;s &lt;code&gt;JoinHandle&lt;&#x2F;code&gt; was the first in the ecosystem,
and I pushed that we should model it using the &quot;detach-on-drop&quot; behavior
directly after &lt;code&gt;std::thread::JoinHandle&lt;&#x2F;code&gt;. What I didn&#x27;t account for though,
is that threads cannot be cancelled externally: &lt;code&gt;std::thread::JoinHandle&lt;&#x2F;code&gt;
doesn&#x27;t, and may likely never have a &lt;code&gt;cancel&lt;&#x2F;code&gt; method &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#cancel-thread&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;cancel-thread&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;The way a thread can be cancelled from the outside is
by passing a channel to the thread, and cancelling when a message is received.
Unlike async Rust, threads don&#x27;t have &lt;code&gt;.await&lt;&#x2F;code&gt; points which act as natural
stopping points. So instead threads have to opt-in to cancellation by manually
listening for signals.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Failing to propagate cancellation means that if we cancel a tree of work, we
may end up with &lt;strong&gt;dangling tasks&lt;&#x2F;strong&gt; that continue when we really don&#x27;t want to.
Rather than having a &lt;code&gt;cancel&lt;&#x2F;code&gt; method which allows us to manually opt-in to
cancellation propatation (more on that later), cancellation propagation should
be opt-out by default.&lt;&#x2F;p&gt;
&lt;p&gt;Luckily we don&#x27;t need to guess what a runtime with &quot;cancellation propagation is
opt-out&quot; behavior would look like. The
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-task&#x2F;4.0.3&#x2F;async_task&#x2F;struct.Task.html&quot;&gt;&lt;code&gt;async-task&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
executor, and in turn &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;smol&#x2F;1.2.5&#x2F;smol&#x2F;&quot;&gt;&lt;code&gt;smol&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; runtime do
exactly that.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;smol::block_on(async {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; task = smol::spawn(async {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    });
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;(task);
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;done&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;&amp;gt; 1
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; done
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;patching-cancellation-propagation&quot;&gt;Patching cancellation propagation&lt;&#x2F;h2&gt;
&lt;p&gt;Unfortunately only &lt;code&gt;smol&lt;&#x2F;code&gt; propagates cancellation across tasks, and it would be
a breaking change to modify the cancellation propagation behavior of
&lt;code&gt;JoinHandle&lt;&#x2F;code&gt; in other runtimes.&lt;&#x2F;p&gt;
&lt;p&gt;Users of runtimes can still ensure that cancellation will always correctly be
propagated by creating a custom &lt;code&gt;spawn&lt;&#x2F;code&gt; function that contains a drop guard like
so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;tokio::task;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;core::future::Future;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;core::pin::Pin;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;core::task::{Context, Poll};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Spawn a new tokio Task and cancel it on drop.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;future&lt;&#x2F;span&gt;&lt;span&gt;: T) -&amp;gt; Wrapper&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;T::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    T: Future + Send + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;T::&lt;&#x2F;span&gt;&lt;span&gt;Output: Send + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    Wrapper(task::spawn(future))
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Cancels the wrapped tokio Task on Drop.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Wrapper&amp;lt;T&amp;gt;(task::JoinHandle&amp;lt;T&amp;gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; Future &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Wrapper&amp;lt;T&amp;gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output = Result&amp;lt;T, task::JoinError&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Pin::new_unchecked(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) }.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(cx)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; Drop &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Wrapper&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; do `let _ = self.0.cancel()` for `async_std::task::Task`
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;abort&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This wrapper can be adapted to work for &lt;code&gt;async-std&lt;&#x2F;code&gt; as well, and ensures that
cancellation propagates across task bounds.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;structured-concurrency&quot;&gt;Structured concurrency&lt;&#x2F;h2&gt;
&lt;p&gt;Given we&#x27;re talking a lot about propagating cancellation and trees in this post,
we probably should mention the concept of &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Structured_concurrency&quot;&gt;&quot;structured
concurrency&quot;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In order for async Rust to be structurally concurrent I think of tasks as having
the following requirements:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Ensure &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#ensure&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; sure child tasks don&#x27;t outlive their parents.&lt;&#x2F;li&gt;
&lt;li&gt;If we cancel a parent task the child task should be cancelled too.&lt;&#x2F;li&gt;
&lt;li&gt;If a child task raises an error, the parent task should be able to act on it.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;ensure&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;More on whether we can actually ensure this later on in this post.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This structure makes it so errors don&#x27;t accidentally go ignored, or we fail to
cancel tasks further down in the tree. It&#x27;s the basis for effectively
implementing other mechanisms on top, such as retries, limits, supervisors, and
transactions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cancelling-a-group-of-tasks&quot;&gt;Cancelling a group of tasks&lt;&#x2F;h2&gt;
&lt;p&gt;Cancellation becomes more difficult to implement when we&#x27;re dealing with a
stream of tasks, each of which needs to be spawned on the runtime. Currently a
lot of async code just spawns tasks, detaches them, and logs if case of an
error:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The async-std &amp;quot;echo tcp server&amp;quot; example.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::io;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::net::{TcpListener, TcpStream};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::task;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Listen for new TCP connections on port 8080.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; listener = TcpListener::bind(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Iterate over the incoming connections, and move each task to a multi-threaded
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; runtime.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; incoming = listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;incoming&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(stream) = incoming.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().await {
&lt;&#x2F;span&gt;&lt;span&gt;    task::spawn(async {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; If an error occurs, log it to stderr.
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span&gt;Err(err) = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(stream).await {
&lt;&#x2F;span&gt;&lt;span&gt;            eprintln!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;error: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, err);
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    });
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The main logic of our listen loop. This is a simple echo server.
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;stream&lt;&#x2F;span&gt;&lt;span&gt;: io::Result&amp;lt;TcpStream&amp;gt;) -&amp;gt; io::Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; stream = stream?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(reader, writer) = &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;stream, &amp;amp;stream);
&lt;&#x2F;span&gt;&lt;span&gt;    io::copy(reader, writer).await?;
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But if we&#x27;re trying to do &lt;a href=&quot;https:&#x2F;&#x2F;docs.swift.org&#x2F;swift-book&#x2F;LanguageGuide&#x2F;Concurrency.html&quot;&gt;Structured
Concurrency&lt;&#x2F;a&gt;
correctly, we need to ensure cancellation propagates to those spawned tasks too.
In order to do so we need to introduce a new async primitive to Rust: the
&lt;code&gt;TaskGroup&lt;&#x2F;code&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#scope&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;scope&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;&#x2F;sup&gt;
&lt;p&gt;This terminology is borrowed from Swift, but is similar-ish to how
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;crossbeam&#x2F;0.8.1&#x2F;crossbeam&#x2F;&quot;&gt;&lt;code&gt;crossbeam-scope&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; works (n threads
managed by a central point). However unlike &lt;code&gt;crossbeam-scope&lt;&#x2F;code&gt;, the name concerns
itself less with how the lifetimes flow, and more how you can reason about how
it should be used.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;To my knowledge no runtimes currently support this out of the box, but crates
for this exist on crates.io. One example of such a crate is
&lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;task-group&quot;&gt;&lt;code&gt;task-group&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, authored by the Fastly WASM
group. Functionally it allows creating a group of tasks which act as a single
unit. If a task errors or panics, all other tasks are cancelled. And when the
&lt;code&gt;TaskManager&lt;&#x2F;code&gt; is dropped, all currently running tasks are cancelled.&lt;&#x2F;p&gt;
&lt;p&gt;Task grouping (including task scopes) is a topic that needs its own blog post.
But if you&#x27;re looking to apply cancellation propagation to a stream of items, at
least now you know this is the primitive that enables that to work.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;halt-safety&quot;&gt;halt-safety&lt;&#x2F;h2&gt;
&lt;p&gt;So far we&#x27;ve talked a fair bit about cancellation in this post. Now that we know
that the existence of &lt;code&gt;.await&lt;&#x2F;code&gt; means that our function might exit, it&#x27;s natural
to ask: &lt;em&gt;&quot;If our Future&#x27;s state machines can be cancelled at any state, how do
we ensure they function correctly?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;When we&#x27;re using futures created through &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt;, cancellation at
&lt;code&gt;.await&lt;&#x2F;code&gt; points will functionally act no different than early returns through
the try (&lt;code&gt;?&lt;&#x2F;code&gt;) operator.&lt;&#x2F;strong&gt; In both cases function execution is halted,
destructors are run, and resources are cleaned up. Take the following example;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Regardless of where in the function we stop execution, destructors will be
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; run and resources will be cleaned up.
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;do_something&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: PathBuf) -&amp;gt; io::Result&amp;lt;Output&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;                                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 1. the future is not guaranteed to progress after instantiation
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; file = fs::open(&amp;amp;path).await?;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 2. `.await` and 3. `?` can cause the function to halt
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;parse&lt;&#x2F;span&gt;&lt;span&gt;(file).await;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 4. `.await` can the function to halt
&lt;&#x2F;span&gt;&lt;span&gt;    res                                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 5. execution has finished, return a value
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;do_something&lt;&#x2F;code&gt; has 5 distinct points where it can halt execution and destructors
are run. It doesn&#x27;t matter whether &lt;code&gt;.await&lt;&#x2F;code&gt; triggers a cancellation, &lt;code&gt;?&lt;&#x2F;code&gt; returns
an error, or our function exits as expected. Our destructors don&#x27;t need to care,
they only need to concern themselves with is ensuring they release whatever
resources they&#x27;re holding onto &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#halt-safety&quot;&gt;9&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;halt-safety&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;9&lt;&#x2F;sup&gt;
&lt;p&gt;&quot;Clean up resources regardless of what triggered the function to
halt&quot; is what I&#x27;m referring to as &quot;halt-safety&quot;. I&#x27;m not in love with the term,
but I needed to find a way to give a name to this group of mechanisms. I hope
the term is clear enough.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Things change a bit when we talk about Futures created using manual
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;task&#x2F;enum.Poll.html&quot;&gt;&lt;code&gt;Poll&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; state machines.
Within a manual state machine we don&#x27;t call &lt;code&gt;.await&lt;&#x2F;code&gt;; instead we make forward
progress by manually calling &lt;code&gt;Future::poll&lt;&#x2F;code&gt; or &lt;code&gt;Stream::poll_next&lt;&#x2F;code&gt;. Similar when
dealing with &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; we want to ensure that destructors are run should
any of &lt;code&gt;poll_*&lt;&#x2F;code&gt;, &lt;code&gt;?&lt;&#x2F;code&gt;, or &lt;code&gt;return&lt;&#x2F;code&gt; run. &lt;strong&gt;Unlike &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; futures,
resiliency against our function halting isn&#x27;t automatically provided for us.
Instead manually authored futures need to implement the resiliency that
&lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; futures rely on.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I like to think about a futures call graph like a tree. There are the leaf
nodes in the tree, which need to guarantee cancellation is handled correctly.
And there are branch nodes in the tree, which are all created through
&lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; and rely on the leaf nodes correctly implementing resource
cleanups.&lt;&#x2F;p&gt;
&lt;p&gt;Kind of like how in non-async Rust we don&#x27;t really need to think about releasing
file handles or memory since we rely on that just working out of the box. The
only time we really need to think about how to release resources, is when we&#x27;re
implementing primitives like &lt;code&gt;TcpStream&lt;&#x2F;code&gt; or &lt;code&gt;Vec&lt;&#x2F;code&gt; ourselves.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;should-tasks-be-detachable&quot;&gt;Should tasks be detachable?&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;ve talked quite a bit about the importance of cancellation propagation for
tasks, perhaps to the point that you might now be wondering whether tasks should
be detachable at all. Unfortunately &lt;a href=&quot;https:&#x2F;&#x2F;cglab.ca&#x2F;~abeinges&#x2F;blah&#x2F;everyone-poops&#x2F;&quot;&gt;destructors in Rust are not guaranteed to
run&lt;&#x2F;a&gt;, so we can&#x27;t can&#x27;t
actually stop people from passing &lt;code&gt;JoinHandle&lt;&#x2F;code&gt;s to &lt;code&gt;mem::forget&lt;&#x2F;code&gt; in order to
detach their tasks.&lt;&#x2F;p&gt;
&lt;p&gt;That does not mean that we should make detaching tasks easy though. For example:
&lt;code&gt;MutexGuard&lt;&#x2F;code&gt; can be passed to &lt;code&gt;mem::forget&lt;&#x2F;code&gt; too, but we don&#x27;t expose a method
for that directly on &lt;code&gt;MutexGuard&lt;&#x2F;code&gt; because doing so causes the lock to be held
forever. Depending on how we feel about dangling tasks, we may want to use API
design to disincentivize people from going into unwanted states.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;an-async-trait-which-can-t-be-cancelled&quot;&gt;An async trait which can&#x27;t be cancelled?&lt;&#x2F;h2&gt;
&lt;p&gt;There has been talk in the Async Foundations WG about potentially
creating a new async trait that would create a future which guarantees it
must be run to completion (e.g. &quot;can&#x27;t be cancelled&quot;). Our existing
&lt;code&gt;core::future::Future&lt;&#x2F;code&gt; trait would inherit from that trait, and add the
additional guarantee that it can in fact be cancelled.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve seen two main motivations for going in this direction:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;FFI compatibility with C++&#x27;s async system, where failing to run a &quot;C++
Future&quot; to completion is undefined behavior.&lt;&#x2F;li&gt;
&lt;li&gt;It would make it easier for non-experts to author async Rust by making
&quot;cancellation&quot; something you don&#x27;t need to learn about up front.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This is not the right post to dig into the first point, but the second point
certainly is interesting for us here.  While I agree this may indeed pose a
hurdle for people writing async today, I don&#x27;t believe it will going forward
because of the work we&#x27;re doing to eliminate the need to manually author &lt;code&gt;Poll&lt;&#x2F;code&gt;
state machines already. Work is currently ongoing to for example change the
signature of &lt;code&gt;Stream&lt;&#x2F;code&gt; from &lt;code&gt;fn poll_next&lt;&#x2F;code&gt; to &lt;code&gt;async fn next&lt;&#x2F;code&gt;. Similarly the
working group is working on adding async traits and async closures, all with the
goal to reduce the need to author futures by hand.&lt;&#x2F;p&gt;
&lt;p&gt;As we&#x27;ve observed, handling cancellation is most difficult when authoring
futures by hand. As that is where we need to build the resiliency to halts
(through cancellation and errors alike) that the rest of the futures call graph
relies upon. &lt;strong&gt;If we make it so that manually authored futures are only required
to implement the primitives that the rest of the ecosystem relies upon, then the
problem has already been solved.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To close this out: I think Rust&#x27;s general approach to ensuring {&lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rfcs&#x2F;3128-io-safety.html&quot;&gt;IO
safety&lt;&#x2F;a&gt;, memory
safety, halt safety} should be multi-pronged. We should make it so that for the
vast majority of operations, operators shouldn&#x27;t need to reach for Rust&#x27;s
powertools. But for when powertools are definitely the way to go, we should add
all the lints and hints we can to ensure they&#x27;re operated safely &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#example&quot;&gt;10&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;example&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;10&lt;&#x2F;sup&gt;
&lt;p&gt;For example, if I ever need to author something using
[&lt;code&gt;MaybeUninit&lt;&#x2F;code&gt;], I want the compiler to remind me to &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;blob&#x2F;master&#x2F;library&#x2F;core&#x2F;src&#x2F;array&#x2F;mod.rs#L646-L662&quot;&gt;author a drop
guard&lt;&#x2F;a&gt;
when keeping it live past something which may panic. Perhaps someday (:&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;intermediate-matching-on-cancellation&quot;&gt;intermediate matching on cancellation?&lt;&#x2F;h2&gt;
&lt;p&gt;While editing this post, I heard of a possible third motivation to potentially
have an alternate future trait: wanting the ability to match on cancellation.
The idea is that we can replace &lt;code&gt;?&lt;&#x2F;code&gt; with &lt;code&gt;match&lt;&#x2F;code&gt; to handle errors using
alternate logic, but we cannot do at a cancellation point for &lt;code&gt;.await&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Using the Try operator to re-throw the error.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; string = fs::read_to_string(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;my-file.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Manually re-throwing the error.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; string = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span&gt;fs::read_to_string(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;my-file.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await {
&lt;&#x2F;span&gt;&lt;span&gt;    Err(err) =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;Err(err),
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(s) =&amp;gt; s,
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; We can replace the `?` with `match`, but we can&amp;#39;t replace `.await`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; with anything else.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The idea is that in conjunction with an un-cancellable future trait,
cancellation would instead be performed by sending a signal to the underlying IO
resource we&#x27;re waiting on, which would in turn stop what it&#x27;s doing and return
an &lt;code&gt;io::ErrorKind::Interrupted&lt;&#x2F;code&gt; error that should manually be bubbled up by
intermediate futures to where it can be matched on by the caller.&lt;&#x2F;p&gt;
&lt;p&gt;This argument may sound appealing: right now we indeed can&#x27;t destructure
&lt;code&gt;.await&lt;&#x2F;code&gt; into a &lt;code&gt;match&lt;&#x2F;code&gt; statement the way we can with &lt;code&gt;?&lt;&#x2F;code&gt;. So maybe this
mechanism would be useful?&lt;&#x2F;p&gt;
&lt;p&gt;To dive in a little; let&#x27;s assume we have the following tree of futures:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;main
&lt;&#x2F;span&gt;&lt;span&gt;  -&amp;gt; foo (times out after 1 sec)
&lt;&#x2F;span&gt;&lt;span&gt;    -&amp;gt; bar (times out after 3 secs)
&lt;&#x2F;span&gt;&lt;span&gt;      -&amp;gt; task::sleep (wait for 2 secs)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we want to handle the timeout of &lt;code&gt;foo (times out after 1 sec)&lt;&#x2F;code&gt; in our main
function, we could just match on it in either case:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Current method of handling async cancellation.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; dur = Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; string = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span&gt;fs::read_to_string(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;my-file.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;timeout&lt;&#x2F;span&gt;&lt;span&gt;(dur).await {
&lt;&#x2F;span&gt;&lt;span&gt;    Err(err) =&amp;gt; panic!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;timed out!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;),
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(res) =&amp;gt; res?,
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Runtime-signal cancellation.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; dur = Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; string = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span&gt;fs::read_to_string(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;my-file.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;timeout&lt;&#x2F;span&gt;&lt;span&gt;(dur).await {
&lt;&#x2F;span&gt;&lt;span&gt;    Err(ErrorKind::Interrupted) =&amp;gt; panic!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;timed out!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;),
&lt;&#x2F;span&gt;&lt;span&gt;    Err(err) = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; err,
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(s) =&amp;gt; s,
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In practice both approaches have incredibly similar semantics at the calling
side. The main difference is that in the runtime-signal approach we may never
hit the error path. In fact, there is no longer a guarantee that the inner
futures propagate the cancellation. They can instead choose to ignore the
cancellation and (erroneously) attempt to retry. Retries should always be
scheduled alongside timeouts; that way if we timeout once we can retry again. If
the two are de-coupled, retries beyond the first will not have an associated
timeout, and risk hanging forever. This is undesireable, and something we should
steer people away from. And our existing semantics already achieve that.&lt;&#x2F;p&gt;
&lt;p&gt;There may be reasons why we might want to detect cancellation on intermediate
futures, for example for the purpose of providing &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;context-attribute&#x2F;1.0.0&#x2F;context_attribute&#x2F;&quot;&gt;internal
logging&lt;&#x2F;a&gt;. But this
is already possible by combining &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yoshuawuyts&#x2F;futures-concurrency&#x2F;blob&#x2F;c58baacc3d23cf64d372bfca99923340bde8df05&#x2F;src&#x2F;maybe_done.rs&quot;&gt;completion status
tracking&lt;&#x2F;a&gt;
with &lt;code&gt;Drop&lt;&#x2F;code&gt; guards.&lt;&#x2F;p&gt;
&lt;p&gt;This is further complicated by the fact that we&#x27;re now overloading
&lt;code&gt;io::ErrorKind::Interrupted&lt;&#x2F;code&gt; to carry cancellations from both the operating
system, and trigger in user space. Errors cause by the operating system should
be retried in-place. But errors cause by users should always bubble up. We can
no longer tell them apart.&lt;&#x2F;p&gt;
&lt;p&gt;Another issue is that in order to uniformly support cancellation of futures
futures must now need to carry an &lt;code&gt;io::Result&lt;&#x2F;code&gt; in their return type. We&#x27;d need
to rewrite I&#x2F;O primitives such as
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.10.0&#x2F;async_std&#x2F;task&#x2F;fn.sleep.html&quot;&gt;&lt;code&gt;task::sleep&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
to be fallible just for this purpose. It&#x27;s not the worst; but it is reminescent
of the Futures 0.1 days, where futures had &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.1.31&#x2F;futures&#x2F;future&#x2F;trait.Future.html#associated-types&quot;&gt;always had to be
fallible&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Overall I do think both approaches are roughly comparable. But because the
cancellation-through-signals variant enables cancellations to be ignored
(accidental, or otherwise), it exposes a set of footguns to users of async that
our current system does not have &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#risks&quot;&gt;11&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;risks&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;11&lt;&#x2F;sup&gt;
&lt;p&gt;This is probably worth an entire blog post on its own. But I
have so many posts on in-progress already that I figured I&#x27;d add it in here.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;defer-blocks&quot;&gt;Defer blocks?&lt;&#x2F;h2&gt;
&lt;p&gt;The mechanisms to guard against halt-safety are similar to those for &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;panic&#x2F;trait.UnwindSafe.html&quot;&gt;unwind
safety&lt;&#x2F;a&gt;: create a
drop guard to ensure we run our destructors. Manually writing these &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;blob&#x2F;master&#x2F;library&#x2F;core&#x2F;src&#x2F;array&#x2F;mod.rs#L646-L697&quot;&gt;can get
pretty
verbose&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Languages such as Swift and Go provide a language-level solution to this, in the
form of the &lt;code&gt;defer&lt;&#x2F;code&gt; keyword. This effectively allows users of the language to
write an in-line drop guard to create an anonymous destructor. &lt;a href=&quot;https:&#x2F;&#x2F;www.hackingwithswift.com&#x2F;new-syntax-swift-2-defer&quot;&gt;&quot;The defer
keyword in Swift: try&#x2F;finally done
right&quot;&lt;&#x2F;a&gt; is a thorough
overview of how this works in Swift. But for illustrative purposes, here&#x27;s an
example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;swift&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-swift &quot;&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;func &lt;&#x2F;span&gt;&lt;span&gt;writeLog() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; file = openFile()
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;defer&lt;&#x2F;span&gt;&lt;span&gt; { closeFile(file) }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; hardwareStatus = fetchHardwareStatus()
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;guard&lt;&#x2F;span&gt;&lt;span&gt; hardwareStatus != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&amp;quot;disaster&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt; { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;* defer block runs here *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt; }
&lt;&#x2F;span&gt;&lt;span&gt;    file.write(hardwareStatus)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; defer block runs here
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Rust&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;scopeguard&#x2F;1.1.0&#x2F;scopeguard&#x2F;#macros&quot;&gt;scopeguard crate&lt;&#x2F;a&gt;
provides a collection of &lt;code&gt;defer&lt;&#x2F;code&gt; macros. But these wouldn&#x27;t suffice for &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;blob&#x2F;master&#x2F;library&#x2F;core&#x2F;src&#x2F;array&#x2F;mod.rs#L646-L697&quot;&gt;the
example we shared
earlier&lt;&#x2F;a&gt;,
since we want to maintain access to the data while continuing to access it, and
&lt;a href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=stable&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=5c09b400068a6b14e588e5dfaebe7e9b&quot;&gt;&lt;code&gt;scopeguard::defer&lt;&#x2F;code&gt; doesn&#x27;t let
us&lt;&#x2F;a&gt;.
This is because what we want is drop guards to not take ownership of the value
until the destructor is run. I believe this is also referred to as &lt;em&gt;late
binding&lt;&#x2F;em&gt;. And the best way we could achieve that would be by introducing a
language feature.&lt;&#x2F;p&gt;
&lt;p&gt;To be clear: I&#x27;m not necessarily advocating we introduce &lt;code&gt;defer&lt;&#x2F;code&gt; into Rust. It
would add a form of non-linear control flow to the language which could confuse
a lot of folks &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#callbacks&quot;&gt;12&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. But if we consider &lt;code&gt;{halt, unwind}&lt;&#x2F;code&gt;-safety to be
important enough that we want to provide users with better tools; then &lt;code&gt;defer&lt;&#x2F;code&gt;
seems like a candidate we may want to explore more closely.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;callbacks&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;12&lt;&#x2F;sup&gt;
&lt;p&gt;Folks have told me this from using other languages. I&#x27;ve never
actually used &lt;code&gt;defer&lt;&#x2F;code&gt;, so I can&#x27;t comment on what it&#x27;s like. But I have done a
lot of non-linear control flow by writing callback-heavy JavaScript, and that
indeed takes some getting used to.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;em&gt;update (2021-11-14):&lt;&#x2F;em&gt; as folks correctly pointed out, while
&lt;code&gt;scopeguard::defer!&lt;&#x2F;code&gt; does not provide provide access to the captured values
before dropping,
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;scopeguard&#x2F;1.1.0&#x2F;scopeguard&#x2F;struct.ScopeGuard.html&quot;&gt;&lt;code&gt;scopeguard::ScopeGuard&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
does via the &lt;code&gt;Deref&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;DerefMut&lt;&#x2F;code&gt; traits. The flexibility of being able to
remove the &lt;code&gt;Drop&lt;&#x2F;code&gt; impl of the guard by converting the guard into its inner value
makes for a compelling argument that solving in-line drop impls would be better
solved through a library addition than through a language item.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cancellation-and-io-uring&quot;&gt;Cancellation and io_uring&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;This section was added on 2021-11-17, after the post was initially published.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;pcwalton&quot;&gt;Patrick Walton&lt;&#x2F;a&gt; asked the following question
&lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;qrhg39&#x2F;comment&#x2F;hkaow9n&#x2F;?utm_source=reddit&amp;amp;utm_medium=web2x&amp;amp;context=3&quot;&gt;&#x2F;r&#x2F;rust&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;One motivation for completion futures that either wasn&#x27;t mentioned or is an
unexpected side effect of point #1 (compatibility with C++) is that async code
in C&#x2F;C++ can take non-owning references into buffers. For example, on Linux if
you issue an async read() call using io_uring and you later get cancelled, you
have to tell the kernel somehow that it needs to not touch the buffer after Rust
frees it. There are ways to do this, such as giving the kernel ownership of the
buffers using IORING_REGISTER_BUFFERS, but having the kernel own the I&#x2F;O buffers
can make things awkward. (Async C++ folks have shown me patterns that would
require copies in this case.) Have you all given any thought as to the best
practices here? It&#x27;s a tough decision, as the only real solution I can think of
involves making poll() unsafe, which is unsavory (NB: not necessarily wrong).&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;withoutboats&quot;&gt;Saoirse&lt;&#x2F;a&gt; wrote &lt;a href=&quot;https:&#x2F;&#x2F;without.boats&#x2F;blog&#x2F;io-uring&#x2F;&quot;&gt;an excellent
overview&lt;&#x2F;a&gt; of how the completion-based
&lt;a href=&quot;https:&#x2F;&#x2F;kernel.dk&#x2F;io_uring.pdf&quot;&gt;Linux &lt;code&gt;io_uring&lt;&#x2F;code&gt; family of kernel APIs&lt;&#x2F;a&gt;
interacts with cancellation in Rust. The whole post is worth a read as it covers
much of the nuance and safety considerations involved when using &lt;code&gt;io_uring&lt;&#x2F;code&gt; with
Rust. But it also directly answers Patrick&#x27;s question:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;So I think this is the solution we should all adopt and move forward with:
io-uring controls the buffers, the fastest interfaces on io-uring are the
buffered interfaces, the unbuffered interfaces make an extra copy. We can stop
being mired in trying to force the language to do something impossible.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve looked at how cancellation works for futures and tasks. We&#x27;ve
covered how cancellation propagation ought to work, and how we can backport it
to existing runtimes. And finally we&#x27;ve covered how to reason about structured
concurrency, how cancellation propagation can be applied to groups of tasks, and how
async cancellation might interact with async designs currently being drafted.&lt;&#x2F;p&gt;
&lt;p&gt;I hope this was informative! You might have noticed the title of this post has a
&quot;1&quot; appended to it.  I&#x27;m planning to post a follow-up to this post covering the
design space of triggering cancellation at a distance, and possibly another on
task grouping.  working on different posts on async concurrency, so expect more
on that soon.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve gone and &lt;a href=&quot;https:&#x2F;&#x2F;internals.rust-lang.org&#x2F;t&#x2F;blog-post-async-cancellation&#x2F;15591&quot;&gt;opened a discussion thread on
Internals&lt;&#x2F;a&gt;.
And if you enjoyed this post, and would like to see whatever I&#x27;m dreaming up in
a real-time fashion, you can follow me
&lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;yoshuawuyts&quot;&gt;@yoshuawuyts&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Update (2021-11-14):&lt;&#x2F;em&gt; Firstyear &lt;a href=&quot;https:&#x2F;&#x2F;fy.blackhats.net.au&#x2F;blog&#x2F;html&#x2F;2021&#x2F;11&#x2F;14&#x2F;transactional_operations_in_rust.html&quot;&gt;wrote a follow-up to this
post&lt;&#x2F;a&gt;
on transactional operations in Rust, and how they interact with (async)
cancellation and halt-safety. If you&#x27;re interested in transactions and
rollbacks, I recommend giving it a read!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Thanks to: Eric Holk, Ryan Levick, Irina Shestak, and Francesco Cogno for
helping review this post prior to publishing. And thanks to Niko Matsakis for
walking me through some of the alternate futures (lol) of the future trait.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Futures Concurrency II: A Trait Approach</title>
            <pubDate>Thu, 02 Sep 2021 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/futures-concurrency-2/</link>
            <guid>https://blog.yoshuawuyts.com/futures-concurrency-2/</guid>
            <description>&lt;p&gt;It&#x27;s been exactly two years since I wrote about &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;futures-concurrency&#x2F;&quot;&gt;futures
concurrency&lt;&#x2F;a&gt;. Some work has
happened since, and I figured it would be a good time to recap futures
concurrency, and share some of the new developments.&lt;&#x2F;p&gt;
&lt;p&gt;In this post we&#x27;ll establish a base model of async concurrency for Rust. We&#x27;ll
cover ergonomic new APIs to implement said model. And finally we&#x27;ll describe a
plausible path towards inclusion of those APIs in the stdlib in the short-term.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;modes-of-concurrency&quot;&gt;Modes of concurrency&lt;&#x2F;h2&gt;
&lt;p&gt;Concurrency can be thought of as awaiting multiple things at the same time on
the same thread. Generally we can divide the various modes of concurrency up
along two axes:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Do we want to wait for all outputs, or just the first output?&lt;&#x2F;li&gt;
&lt;li&gt;When an error occurs, do we keep going or do we return early (&quot;short circuit&quot;)?&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;As of August 2020, JavaScript has had the following &lt;code&gt;Promise&lt;&#x2F;code&gt; concurrency APIs
available on most platforms:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Wait for all outputs&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Wait for first output&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Continue on error&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;JavaScript&#x2F;Reference&#x2F;Global_Objects&#x2F;Promise&#x2F;allSettled&quot;&gt;&lt;code&gt;Promise.allSettled&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;JavaScript&#x2F;Reference&#x2F;Global_Objects&#x2F;Promise&#x2F;any&quot;&gt;&lt;code&gt;Promise.any&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Return early on error&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;JavaScript&#x2F;Reference&#x2F;Global_Objects&#x2F;Promise&#x2F;all&quot;&gt;&lt;code&gt;Promise.all&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;JavaScript&#x2F;Reference&#x2F;Global_Objects&#x2F;Promise&#x2F;race&quot;&gt;&lt;code&gt;Promise.race&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;JavaScript covers most concurrency uses really well. Rust has a counterpart to
JavaScript&#x27;s &lt;code&gt;Promise&lt;&#x2F;code&gt; type in &lt;code&gt;Future&lt;&#x2F;code&gt;, but it differs in two key ways:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Promise&lt;&#x2F;code&gt;s are always fallible, while &lt;code&gt;Future&lt;&#x2F;code&gt;s have the option not to be.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Promise&lt;&#x2F;code&gt;s start executing immediately, while &lt;code&gt;Future&lt;&#x2F;code&gt;s need to be invoked
first. &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#future-promise&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;future-promise&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;In terms of execution, the rough equivalent of a &lt;code&gt;Promise&lt;&#x2F;code&gt; in
JavaScript is
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.10.0&#x2F;async_std&#x2F;task&#x2F;index.html&quot;&gt;&lt;code&gt;Task&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; in Rust
(starts executing immediately on creation).
The rough equivalent of a &lt;code&gt;Future&lt;&#x2F;code&gt; in Rust is a
&lt;a href=&quot;https:&#x2F;&#x2F;javascript.plainenglish.io&#x2F;the-benefit-of-the-thenable-object-in-javascript-78107b697211&quot;&gt;&quot;thenable&quot;&lt;&#x2F;a&gt;
in JavaScript (starts executing once &lt;code&gt;await&lt;&#x2F;code&gt;ed).&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;For &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.10.0&#x2F;async_std&#x2F;&quot;&gt;&lt;code&gt;async-std&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; we&#x27;ve been
experimenting with introducing similar concurrency APIs as those found for
JavaScript &lt;code&gt;Promise&lt;&#x2F;code&gt;s as part of our &lt;code&gt;future&lt;&#x2F;code&gt; submodule. For Rust &lt;code&gt;Futures&lt;&#x2F;code&gt;
which don&#x27;t return &lt;code&gt;Result&lt;&#x2F;code&gt; we expose two methods for concurrency:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;Wait for all outputs&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Wait for first output&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Future::join&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::race&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;When we add &lt;em&gt;fallability&lt;&#x2F;em&gt; to the mix (e.g. return a &lt;code&gt;Result&lt;&#x2F;code&gt; from the future)
&lt;code&gt;async-std&lt;&#x2F;code&gt;&#x27;s &lt;code&gt;try_&lt;&#x2F;code&gt; methods for concurrency become available we can compare it
1:1 to JavaScript&#x27;s APIs:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Wait for all outputs&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Wait for first output&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Continue on error&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::join&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::try_race&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Return early on error&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::try_join&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Future::race&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;The &lt;code&gt;try&lt;&#x2F;code&gt; prefix can be thought of as inverting the semantics of the method. In
the case of &lt;code&gt;try_join&lt;&#x2F;code&gt; we no longer wait for &lt;em&gt;all&lt;&#x2F;em&gt; items to complete; on error
we&#x27;ll now exit early and cancel all others. In the case of &lt;code&gt;try_race&lt;&#x2F;code&gt; we no
longer wait for the &lt;em&gt;first&lt;&#x2F;em&gt; item to complete; on error we&#x27;ll keep waiting until
we either find a successful item or run out of items.&lt;&#x2F;p&gt;
&lt;p&gt;This is the model we wrote about two years ago, and aside from a rename
(&lt;code&gt;select&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;race&lt;&#x2F;code&gt;) it&#x27;s remained identical. However despite that, we still
haven&#x27;t attempted to introduce this functionality into the stdlib yet. And
that&#x27;s because of missing ✨ language features ✨.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;joining-tuples&quot;&gt;Joining tuples&lt;&#x2F;h2&gt;
&lt;p&gt;In my post &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;future-join-and-const-eval&#x2F;&quot;&gt;&quot;&lt;code&gt;future::join&lt;&#x2F;code&gt; and
const-eval&quot;&lt;&#x2F;a&gt; I talk
about the issue of joining multiple futures:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;[...] once we start joining more than two futures, the output types become different:&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(join!(a, b, c).await, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(b).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(c).await, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;))); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; oh no!
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;As you can see, each invocation of Future::join returns a tuple. But that
means that chaining calls to it starts to nest tuples, which becomes hard to
use. And it becomes more nested the more times you chain. Oh no!&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;In the post we explain that until then we&#x27;d been solving this &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#this&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; by using a &lt;code&gt;join!&lt;&#x2F;code&gt;
macro, which by nature is variadic &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#variadic&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. However ideally we would be
able to write methods which are generic over tuples. Not only would that allow
us to write a better &lt;code&gt;join&lt;&#x2F;code&gt; function, it would also save us from having stdlib
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;primitive.tuple.html&quot;&gt;twelve different &lt;code&gt;PartialEq&lt;&#x2F;code&gt; and &lt;code&gt;PartialOrd&lt;&#x2F;code&gt;
impls&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;this&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;&quot;this&quot; means having nested return types like &lt;code&gt;Join&amp;lt;Join&amp;lt;Join&amp;lt;A&amp;gt;, B&amp;gt;, C&amp;gt;&lt;&#x2F;code&gt; which return tuples in the shape of &lt;code&gt;(a, (b, c))&lt;&#x2F;code&gt;, etc. What we want is to
be able to have a single &quot;flat&quot; &lt;code&gt;Join&amp;lt;A, B, C...&amp;gt;&lt;&#x2F;code&gt; return type which returns
&lt;code&gt;(a, b, c)&lt;&#x2F;code&gt; without any nesting. That&#x27;s the challenge we&#x27;re trying to solve.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;variadic&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;&quot;Variadic&quot; means &quot;can support any number of arguments&quot;. For example
&lt;code&gt;println!&lt;&#x2F;code&gt; can  print out any number of arguments. We can&#x27;t express that using
regular Rust functions yet.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Just like &lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rfcs&#x2F;2000-const-generics.html&quot;&gt;const
generics&lt;&#x2F;a&gt; solved the
a similar issue for arrays, it seems likely like we&#x27;ll eventually want to solve
this for tuples too. But that&#x27;s unlikely to happen anytime soon (if I&#x27;d hazard a
guess, I&#x27;d say if work starts on this in 2022, then maybe we could have it by
2023?). So for now we need to work around this restriction, and luckily there
are a few options.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-to-expose-futures-concurrency&quot;&gt;How to expose futures concurrency&lt;&#x2F;h2&gt;
&lt;p&gt;In response to &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;future-join-and-const-eval&#x2F;&quot;&gt;&quot;&lt;code&gt;future::join&lt;&#x2F;code&gt; and
const-eval&quot;&lt;&#x2F;a&gt;, matthieum
&lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;kyjprs&#x2F;blog_post_futurejoin_and_consteval&#x2F;gjhb50a&#x2F;?utm_source=reddit&amp;amp;utm_medium=web2x&amp;amp;context=3&quot;&gt;pointed
out&lt;&#x2F;a&gt;
we can invert the API instead. Rather than exposing this functionality as functions scoped under
&lt;code&gt;std::future&lt;&#x2F;code&gt;, we could instead extend in-line container types with traits that
allow for more fluent composition. I wrote the
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-concurrency&#x2F;1.0.0&#x2F;futures_concurrency&#x2F;&quot;&gt;&lt;code&gt;futures-concurrency&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
crate to test out that design, and the design feels &lt;em&gt;incredibly&lt;&#x2F;em&gt; good. For
example, this is what it looks like to await multiple similarly-typed futures
without any intermediate allocations:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::future;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_concurrency::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!([a, b, c].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;().await, [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And this is for multiple differently-types futures without any intermediate
allocations:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::future;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_concurrency::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!((a, b, c).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;().await, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But sometimes we want to allocate because we don&#x27;t know how many futures we&#x27;re
going to want to await in parallel. So it works with &lt;code&gt;Vec&amp;lt;Future&amp;gt;&lt;&#x2F;code&gt; as well,
similar to &lt;code&gt;futures&lt;&#x2F;code&gt;&#x27; &lt;code&gt;join_all&lt;&#x2F;code&gt; function:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::future;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures_concurrency::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(vec![a, b, c].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;().await, vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This feels like the most promising approach so far. Once the right traits are in
scope (2024 edition, anyone?), the way to await becomes intuitive. We no longer
need to chain calls to &lt;code&gt;.join().join().join()&lt;&#x2F;code&gt; or wrap items in awkward macros.
Instead we group futures together, suffix it with our preferred method of
concurrency, and then types pop out on the other end. Easy.&lt;&#x2F;p&gt;
&lt;p&gt;There are some caveats to this though. The way we&#x27;ve implemented this for tuples
is the same way the stdlib implements &lt;code&gt;PartialOrd&lt;&#x2F;code&gt; and &lt;code&gt;PartialEq&lt;&#x2F;code&gt;: by using a
macro. However because we&#x27;re returning custom types from these traits, it means
we&#x27;re currently generating &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-concurrency&#x2F;1.0.0&#x2F;futures_concurrency&#x2F;tuple&#x2F;index.html&quot;&gt;twelve different &lt;code&gt;Join&lt;&#x2F;code&gt;
types&lt;&#x2F;a&gt;.
Surely there must be a way around this right?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;async-traits-and-taits&quot;&gt;Async Traits and TAITs&lt;&#x2F;h2&gt;
&lt;p&gt;Currently the &lt;code&gt;futures_concurrency::Join&lt;&#x2F;code&gt; trait is defined like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Join {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Future: Future&amp;lt;Output = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Future;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We have two types: the &lt;code&gt;Output&lt;&#x2F;code&gt; type which is what our method will return once
awaited. And the &lt;code&gt;Future&lt;&#x2F;code&gt; type which is the future our &lt;code&gt;join&lt;&#x2F;code&gt; method will return
that needs to be awaited. However the async foundations WG is working on
introducing &quot;async traits&quot; into the language. Once that&#x27;s in place it&#x27;s expected
we&#x27;ll be able to rewrite the trait like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Join {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s expected that all async traits will go this way, since it removes the need
to manually implement futures using
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;pin&#x2F;index.html&quot;&gt;&lt;code&gt;Pin&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#pin&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; (which is a big
improvement for ergonomics). However this comes with an issue: How do we
manually return futures?&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;pin&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;I consider &lt;code&gt;Pin&lt;&#x2F;code&gt; to be like &lt;code&gt;unsafe {}&lt;&#x2F;code&gt; in that it&#x27;s essential for Rust
to expose this - but under no circumstance should it be required to perform
common operations.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;The answer for that appears to be
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;63063&quot;&gt;TAITS&lt;&#x2F;a&gt; (&quot;Type Alias Impl
Trait&quot;). This allows traits to be used in type aliases, and treated as concrete
types. Async traits hasn&#x27;t been RFC&#x27;d yet, but I expect we&#x27;ll want to enable it
to work with TAITS once they stabilize. So that would allow us to implement the
async trait differently depending on whether we want to name the output type or
not:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Implement the trait using `async fn`.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; Join &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Vec&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output = Vec&amp;lt;T&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Implement the trait using with a named future.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;JoinFuture&amp;lt;T&amp;gt; = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Future&amp;lt;Output = Vec&amp;lt;T&amp;gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;impl&amp;lt;T&amp;gt; Join for Vec&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output = Vec&amp;lt;T&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; JoinFuture&amp;lt;T&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Perhaps you&#x27;re seeing where I&#x27;m going with this, but for tuples we can then
create a shared &lt;code&gt;Join&lt;&#x2F;code&gt; future type for all tuple variants without needing to
have variadics in the language:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;JoinFuture&amp;lt;T&amp;gt; = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Future&amp;lt;T&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Implement `Join` for tuple `(A, B)`.
&lt;&#x2F;span&gt;&lt;span&gt;impl&amp;lt;T, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; N: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; Join for (A, B)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    A: Future,
&lt;&#x2F;span&gt;&lt;span&gt;    B: Future,
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output = (A::Output, B::Output);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; JoinFuture&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; { ... }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ...and repeat for all other tuples (likely using a macro).
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; N: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; JoinTrait &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; (A, B, C) { ... }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; N: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; JoinTrait &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; (A, B, C, D) { ... }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; N: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; JoinTrait &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; (A, B, C, D, E) { ... }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And once we have variadics as part of the language, we could migrate the
implementations to use that instead:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;JoinFuture&amp;lt;T&amp;gt; = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Future&amp;lt;T&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Implement `Join` for all tuples of two or more items.
&lt;&#x2F;span&gt;&lt;span&gt;impl&amp;lt;A, B, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; N: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; Join for (A, B)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    A: Future,
&lt;&#x2F;span&gt;&lt;span&gt;    B...: Future, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; &amp;lt;- Entirely made up variadic syntax
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output = (A::Output, B::Output);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Join&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s important to emphasize though that the semantics of TAITS have not yet been
stabilized, and are subject to change. But the introduction of TAITS may also
have implications for the rest of the language; for example bringing inference
to manual trait implementations too. &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#add&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;add&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;An example of this could be &lt;code&gt;impl Iterator for Foo { fn next(&amp;amp;mut self) -&amp;gt; Option&amp;lt;i32&amp;gt; { ... } } }&lt;&#x2F;code&gt;.
The associated type &lt;code&gt;Item&lt;&#x2F;code&gt; can directly be inferred from &lt;code&gt;fn next&lt;&#x2F;code&gt;&#x27;s return
type. If this was allowed, it would bring the semantics of manual trait
implementations closer to those done via TAITs.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;road-to-std&quot;&gt;Road to std&lt;&#x2F;h2&gt;
&lt;p&gt;Despite what you might think after the last section, we don&#x27;t need to wait until
we have async traits, TAITS, or variadics in the stdlib to provide a good
experience for async concurrency. Instead we can start small, and as more
language features stabilize, incrementally expose more functionality.&lt;&#x2F;p&gt;
&lt;p&gt;The most basic form in which we could introduce &lt;code&gt;Join&lt;&#x2F;code&gt; into the stdlib would be
by making it available for implementation within the stdlib-only using the
&lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;api-guidelines&#x2F;future-proofing.html&quot;&gt;C-SEALED future-proofing
pattern&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Join: private::Sealed {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Future: Future&amp;lt;Output = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Future;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mod &lt;&#x2F;span&gt;&lt;span&gt;private {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;super&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Sealed {}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;super&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Join2 { ... }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Future &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Join2 { ... }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;super::Join &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; (A, B) { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Future = Join2&amp;lt;A, B&amp;gt;; ... }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ...etc
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Because in addition to having the trait be sealed, the returned futures are
private too. The only way to reference the associated futures is through &lt;code&gt;impl Future&lt;&#x2F;code&gt;. Which lines up perfectly with async traits, which would allow us to
drop the &lt;code&gt;Seal&lt;&#x2F;code&gt; and publicly expose the trait as &lt;code&gt;core::future::Join&lt;&#x2F;code&gt; like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Join {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This version still only allows storing the future as &lt;code&gt;impl Future&lt;&#x2F;code&gt;, but once
TAITs land can be extended to named futures instead. And then eventually with
variadics make the final jump to feature completedness.&lt;&#x2F;p&gt;
&lt;p&gt;In summary: if we wanted to, we could start implementing a fully forward
compatible version of &lt;code&gt;Join&lt;&#x2F;code&gt; and related APIs in the stdlib &lt;em&gt;today&lt;&#x2F;em&gt;!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve established a basic model for concurrently executing multiple
futures. We&#x27;ve described an ergonomic new API, prototyped in the
&lt;code&gt;futures_concurrency&lt;&#x2F;code&gt; crate which enables concurrent execution of futures in a
more ergonomic way than was previously possible. And finally we&#x27;ve shown a path
for gradually introducing these APIs into the stdlib in a forward-compatible
manner.&lt;&#x2F;p&gt;
&lt;p&gt;For me, the most important point of this post is to show that it&#x27;s possible to
create Futures concurrency APIs which feel natural to use, and can be called
with little effort. The exact shape of the traits is less important, and
something we can improve on over time. We&#x27;ve shown that we can introduce these
methods in the stdlib in a forward-compatible manner, giving us time to polish
and iterate on these traits as more language features become available.&lt;&#x2F;p&gt;
&lt;p&gt;One mode of execution we didn&#x27;t cover in this post is a variation on &lt;code&gt;race&lt;&#x2F;code&gt; in
which multiple futures are resolved concurrently, and values are yielded as soon
as they&#x27;re resolved. This is what the &lt;code&gt;futures_rs::select!&lt;&#x2F;code&gt; macro is commonly
used for. In a future installment of this series we&#x27;ll take a look at how we
could potentially bring that functionality to the stdlib as well.&lt;&#x2F;p&gt;
&lt;p&gt;Another thing which we haven&#x27;t covered yet is how to introduce the &lt;code&gt;try&lt;&#x2F;code&gt;
variants of the APIs. The obvious choice would be to introduce a &lt;code&gt;TryJoin&lt;&#x2F;code&gt; trait,
but that may not quite be the right fit for what we&#x27;re trying to do. In a future
installment we&#x27;ll look more closely at introducing the &lt;code&gt;try&lt;&#x2F;code&gt; variants.&lt;&#x2F;p&gt;
&lt;p&gt;My plan for the &lt;code&gt;futures-concurrency&lt;&#x2F;code&gt; crate is to keep working on it, and bring
it to a state where all the APIs shared in this post have been implemented. Once
that&#x27;s proven to work, and we&#x27;re sure that this method is forward compatible, we
can consider proposing this for addition to the stdlib.&lt;&#x2F;p&gt;
&lt;p&gt;But that&#x27;s something for the future. For now I hope you enjoy the
&lt;code&gt;futures-concurrency&lt;&#x2F;code&gt; crate, and I&#x27;d be keen to hear what folks think!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Special thanks to: &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;TartanLlama&quot;&gt;Sy Brand&lt;&#x2F;a&gt; for help with
understanding variadics in C++, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;scottmcm&#x2F;&quot;&gt;Scott McMurray&lt;&#x2F;a&gt;
for elaborating on TAITs, and &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;ryan_levick&#x2F;&quot;&gt;Ryan Levick&lt;&#x2F;a&gt;
and &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;theinedibleholk&quot;&gt;Eric Holk&lt;&#x2F;a&gt; for reviewing this post
prior to publishing.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Async overloading</title>
            <pubDate>Tue, 24 Aug 2021 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/async-overloading/</link>
            <guid>https://blog.yoshuawuyts.com/async-overloading/</guid>
            <description>&lt;p&gt;If the stdlib were to expose APIs for async IO, how should it be namespaced?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Like this?
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::async_io::remove_file;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Like this?
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::io::async_remove_file;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Or like this?
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::io::remove_file;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This post looks at async overloading in Swift, how we could potentially
translate it to Rust, and makes the case that we should make investigating its
feasibility a priority for the Async Foundations WG.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;choose-your-calling-convention&quot;&gt;Choose your calling convention&lt;&#x2F;h2&gt;
&lt;p&gt;When designing an API in Rust which performs IO, you have to make a decision
whether you want it to be synchronous, asynchronous, or both.&lt;&#x2F;p&gt;
&lt;p&gt;If you choose &quot;synchronous&quot; it&#x27;s likely easier to write, iterate on,
and use. But it may be less performant, and interacting with async APIs can be
tricky.&lt;&#x2F;p&gt;
&lt;p&gt;Choosing &quot;asynchronous&quot; will often mean better performance (especially on
multi-core machines), better compatibility with a lot of other networking
operations. But it is often significantly harder to author and maintain.&lt;&#x2F;p&gt;
&lt;p&gt;If you author both so you can let end-users decide what they want to
consume, not only will you incur the cost of writing the same code twice. You
also need to choose how to expose both APIs to end-users. This leads to
situations like with the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;mongodb&#x2F;1.2.2&#x2F;mongodb&#x2F;index.html&quot;&gt;&lt;code&gt;mongodb&lt;&#x2F;code&gt;
crate&lt;&#x2F;a&gt; which exposes a
feature-flagged &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;mongodb&#x2F;1.2.2&#x2F;mongodb&#x2F;sync&#x2F;index.html&quot;&gt;&lt;code&gt;sync&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
submodule which exposes a copy of all IO types for use in synchronous code.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s a clear &quot;primary API&quot; (async), and &quot;secondary API&quot; (sync). From a
maintainer&#x27;s perspective this means that whenever a new async API is introduced,
you need to manually ensure that the sync counterpart is used as well. And from
a user&#x27;s perspective you need to make sure you don&#x27;t accidentally call the wrong
API since both live in the same namespace.&lt;&#x2F;p&gt;
&lt;p&gt;Another example are the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;postgres&#x2F;0.19.1&#x2F;postgres&#x2F;&quot;&gt;postgres&lt;&#x2F;a&gt;
and &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio-postgres&#x2F;0.7.2&#x2F;tokio_postgres&#x2F;&quot;&gt;&lt;code&gt;tokio-postgres&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
crates which split the sync&#x2F;async APIs out into two different crates instead.
This solves the namespace problem, but still requires manually ensuring both
APIs are updated.  And end-users still need to remember to import the right
crate for their purpose.&lt;&#x2F;p&gt;
&lt;p&gt;The current state of crates isn&#x27;t &lt;em&gt;unworkable&lt;&#x2F;em&gt;: we know Rust is used in
production, often to great success. But I don&#x27;t think it&#x27;s hard to argue that it
&lt;em&gt;isn&#x27;t particularly great&lt;&#x2F;em&gt; either. The fact that we need feature flags,
submodules, or even separate crates is a direct artifact of the limitations of
Rust as a language required to &lt;em&gt;create good designs&lt;&#x2F;em&gt;, and not an issue with any
of the ecosystem crates.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-standard-library&quot;&gt;The standard library&lt;&#x2F;h2&gt;
&lt;p&gt;There&#x27;s no arguing that Async Rust is hot right now. Companies both large and
small have made commitments to using Rust, and Async in particular is integral
to Rust&#x27;s adoption. The Async WG (which I&#x27;m part of) is looking at integrating
parts of the ecosystem into the stdlib; including core traits, but also
networking abstractions other IO facilities. And unfortunately &lt;strong&gt;the logical
endpoint of our current trajectory would be a significant increase in API
surface of the stdlib&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;As with all things Rust: nothing is certain until it&#x27;s stabilized. But &quot;async
compat&quot; has been a recurring theme, and the Async WG &lt;a href=&quot;https:&#x2F;&#x2F;nikomatsakis.github.io&#x2F;wg-async-foundations&#x2F;vision&#x2F;deliverables&#x2F;portable&#x2F;stdlib.html#preferred-experience&quot;&gt;is looking at ways to
include runtime-independent async APIs in the
stdlib&lt;&#x2F;a&gt;.
Which if we were to add an async counterpart for every IO API currently in the
stdlib, we&#x27;d end up exposing &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.9.0&#x2F;async_std&#x2F;all.html&quot;&gt;over 300 new
types&lt;&#x2F;a&gt; — not accounting for methods.&lt;&#x2F;p&gt;
&lt;p&gt;To get a sense of what this would feel like we can look at other language
runtimes.
&lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;asyncio.html&quot;&gt;Python&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;dotnet&#x2F;csharp&#x2F;programming-guide&#x2F;concepts&#x2F;async&#x2F;using-async-for-file-access#use-appropriate-classes&quot;&gt;C#&lt;&#x2F;a&gt;,
and Node.js all have this sync&#x2F;async split. I&#x27;m most familiar with Node.js which
has 3 different calling conventions (callbacks, async&#x2F;await, blocking). Which in
practice looks like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Delete a file with the default async callback-based API.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;unlink &lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;unlink&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;.&#x2F;tmp&#x2F;foo.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;err&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;err&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;throw &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;err&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;success&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;);
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Delete a file with the recommended async Promise-based API.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;unlink &lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;fs&#x2F;promises&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;await &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;unlink&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;.&#x2F;foo.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;success&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Delete a file with the sync blocking API.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;unlinkSync &lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;unlinkSync&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;.&#x2F;foo.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;success&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Rust&#x27;s counterpart to Node&#x27;s &lt;code&gt;fs.unlink&lt;&#x2F;code&gt; is
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;fs&#x2F;fn.remove_file.html&quot;&gt;&lt;code&gt;std::fs::remove_file&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Say we wanted to expose an async counterpart to it as part of the stdlib. We&#x27;d have a few options:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;We could create a new submodule (e.g. &lt;code&gt;std::async_fs&lt;&#x2F;code&gt;) to contain a full
counterpart of &lt;code&gt;std::fs&lt;&#x2F;code&gt;, including &lt;code&gt;std::async_fs::remove_file&lt;&#x2F;code&gt;. This approach
is similar to how Python supports both
&lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;io.html&quot;&gt;&lt;code&gt;import io&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;asyncio.html&quot;&gt;&lt;code&gt;import asyncio&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;We could add async types directly under &lt;code&gt;std::fs&lt;&#x2F;code&gt;. So we&#x27;d
have both &lt;code&gt;std::fs::remove_file&lt;&#x2F;code&gt; and &lt;code&gt;std::fs::async_remove_file&lt;&#x2F;code&gt;. This approach
is similar to the way Node.js&#x27;s exposes sync APIs. But having to prefix
each call with &lt;code&gt;async_*&lt;&#x2F;code&gt; and suffix with &lt;code&gt;.await&lt;&#x2F;code&gt; doesn&#x27;t make this an appealing
option for Rust.  Which is likely why I haven&#x27;t heard anyone who prefers this
approach over submodules. Even if prefixing submodules could lead to gems such
as &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.9.0&#x2F;async_std&#x2F;sync&#x2F;index.html&quot;&gt;&lt;code&gt;std::async_sync&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#sync&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;sync&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;I don&#x27;t believe the libs team would seriously let &lt;code&gt;async_sync&lt;&#x2F;code&gt; be a
part of the stdlib. I&#x27;ve heard talk about deprecating &lt;code&gt;std::sync&lt;&#x2F;code&gt; and splitting
it into separate submodules such as &lt;code&gt;std::lock&lt;&#x2F;code&gt; and &lt;code&gt;std::atomic&lt;&#x2F;code&gt;. Which means
we&#x27;d likely sooner see a &lt;code&gt;std::async_lock&lt;&#x2F;code&gt; than &lt;code&gt;std::async_sync&lt;&#x2F;code&gt;. But I still
find it amusing to think about an alternate future where we&#x27;d have &lt;code&gt;sync&lt;&#x2F;code&gt;,
&lt;code&gt;async_sync&lt;&#x2F;code&gt;, &lt;code&gt;async&lt;&#x2F;code&gt;, &lt;code&gt;Async&lt;&#x2F;code&gt;, &lt;code&gt;Sink&lt;&#x2F;code&gt;, &lt;code&gt;AsyncSink&lt;&#x2F;code&gt; and &lt;code&gt;Sync&lt;&#x2F;code&gt; in the stdlib.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;But both options share a core issue: APIs still need to be manually matched to
the context they&#x27;re called in. If you&#x27;re in a sync context,
&lt;code&gt;std::async_fs::remove_file&lt;&#x2F;code&gt; cannot be called. You need to create an async
context first.&lt;&#x2F;p&gt;
&lt;p&gt;And likewise if you&#x27;re in an async context: &lt;code&gt;std::fs::remove_file&lt;&#x2F;code&gt; &lt;em&gt;can&lt;&#x2F;em&gt; be
used, but it&#x27;s most likely not what you want: you probably want the async
version instead. This means that depending on the type of context you&#x27;re in,
half the IO APIs in the stdlib would be of no use to you. Which leaves the
question: &lt;strong&gt;Is there a way we could prevent manually needing to match APIs in
the stdlib to their right calling convention?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;async-overloading-in-swift&quot;&gt;Async overloading in Swift&lt;&#x2F;h2&gt;
&lt;p&gt;In an amendment to
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;apple&#x2F;swift-evolution&#x2F;pull&#x2F;1392&quot;&gt;SE-0296: Async Await&lt;&#x2F;a&gt; made last month,
Swift has added support for async overloading which solves this exact problem!
It enables sync and async functions of the same name to be declared in the same
scope, leaving it up to the caller&#x27;s context to determine which variant is the
right one:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;swift&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-swift &quot;&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Existing synchronous API
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;func &lt;&#x2F;span&gt;&lt;span&gt;doSomethingElse() { ... }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; New and enhanced asynchronous API
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;func &lt;&#x2F;span&gt;&lt;span&gt;doSomethingElse() async { ... }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Calling async functions from sync functions triggers an error like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;swift&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-swift &quot;&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;func &lt;&#x2F;span&gt;&lt;span&gt;f() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Compiler error: `await` is only allowed inside `async` functions
&lt;&#x2F;span&gt;&lt;span&gt;  await doSomething()
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But if you&#x27;re trying to call the sync variant of an overloaded function inside
an async function, you&#x27;d see the following error:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;swift&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-swift &quot;&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;func &lt;&#x2F;span&gt;&lt;span&gt;f() async {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Compiler error: Expression is &amp;#39;async&amp;#39; but is not marked with &amp;#39;await&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;  doSomething()
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However it&#x27;s still possible to call the synchronous version of the API by
creating a synchronous context inside the async block:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;swift&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-swift &quot;&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;func &lt;&#x2F;span&gt;&lt;span&gt;f() async {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; f2 = {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; In a synchronous context, the non-async overload is preferred:
&lt;&#x2F;span&gt;&lt;span&gt;    doSomething()
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  f2()
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But async overloading is not required. It&#x27;s still possible to declare async
functions without overloading: they&#x27;ll just only work in async contexts. And
similarly it&#x27;s possible to declare sync functions which will work in all
contexts.&lt;&#x2F;p&gt;
&lt;p&gt;Unlike other languages, Swift will not need to effectively double the API
surface of their stdlib to support their newly added async functionality. From a
user&#x27;s perspective the same API will &quot;work as expected&quot; in both sync and async
contexts. And that is something Rust can learn from.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bringing-async-overloading-to-rust&quot;&gt;Bringing async overloading to Rust&lt;&#x2F;h2&gt;
&lt;p&gt;Now that you know how Swift has solved this issue, it asks the question: Could
we integrate a system like this into Rust. The fact that I&#x27;m talking about this
at all probably gives away that I think we can. But what would that look like?&lt;&#x2F;p&gt;
&lt;p&gt;For async functions, overloading could be easy enough. Adapting the Swift
example we saw earlier, the following should be able to work:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Existing synchronous API
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;do_something_else&lt;&#x2F;span&gt;&lt;span&gt;() { ... }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; New and enhanced asynchronous API
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;do_something_else&lt;&#x2F;span&gt;&lt;span&gt;() { ... }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We could even give a &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;blob&#x2F;master&#x2F;text&#x2F;1210-impl-specialization.md&quot;&gt;specialization
spin&lt;&#x2F;a&gt;
to the API, and make the syntax something like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;default &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;do_something_else&lt;&#x2F;span&gt;&lt;span&gt;() { ... }
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;do_something_else&lt;&#x2F;span&gt;&lt;span&gt;() { ... }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But I don&#x27;t know what the right syntax for this would be. Maybe it would warrant
a different approach altogether! Today, if we try awaiting an async function
inside a synchronous closure, we&#x27;re met with the following diagnostic:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;error[E0728]: `await` is only allowed inside `async` functions and blocks
&lt;&#x2F;span&gt;&lt;span&gt; --&amp;gt; src&#x2F;lib.rs:4:5
&lt;&#x2F;span&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;span&gt;3 | fn f() {
&lt;&#x2F;span&gt;&lt;span&gt;  |    - this is not `async`
&lt;&#x2F;span&gt;&lt;span&gt;4 |     do_something().await;
&lt;&#x2F;span&gt;&lt;span&gt;  |     ^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With the overload added, we can start suggesting fixes for errors like this too &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#diagnostics-output&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.
For example:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;diagnostics-output&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;As an aside; I&#x27;m super excited for &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;pull&#x2F;86532&quot;&gt;the upcoming
diagnostics changes&lt;&#x2F;a&gt;. The diff
view is looking really good! It&#x27;s just a bummer my blog theme doesn&#x27;t allow me
to custom-color diagnostics output yet. For now imagine the diagnostics in my
blog have pretty colors like the compiler does, heh.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;span&gt;help: try removing `.await` from the function call
&lt;&#x2F;span&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;span&gt;3 | async fn f() {
&lt;&#x2F;span&gt;&lt;span&gt;4 -     do_something().await;
&lt;&#x2F;span&gt;&lt;span&gt;4 +     do_something();
&lt;&#x2F;span&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And calling the overloaded sync function from an async context could produce a
diagnostic like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;warning: unused implementer of `Future` that must be used
&lt;&#x2F;span&gt;&lt;span&gt; --&amp;gt; src&#x2F;lib.rs:4:5
&lt;&#x2F;span&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;span&gt;3 | async fn f() {
&lt;&#x2F;span&gt;&lt;span&gt;4 |     do_something();
&lt;&#x2F;span&gt;&lt;span&gt;  |     ^^^^^^^^^^^^^^^
&lt;&#x2F;span&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;span&gt;  = note: this function is called in an async context and uses the async overload
&lt;&#x2F;span&gt;&lt;span&gt;  = note: `#[warn(unused_must_use)]` on by default
&lt;&#x2F;span&gt;&lt;span&gt;  = note: futures do nothing unless you `.await` or poll them
&lt;&#x2F;span&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;span&gt;help: try adding `.await` to the function call
&lt;&#x2F;span&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;span&gt;3 | async fn f() {
&lt;&#x2F;span&gt;&lt;span&gt;4 |     do_something().await;
&lt;&#x2F;span&gt;&lt;span&gt;  |                   ++++++
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Just like in Swift, using the synchronous overload in an async context could be
done by writing:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;f2 &lt;&#x2F;span&gt;&lt;span&gt;= || {
&lt;&#x2F;span&gt;&lt;span&gt;        doSomething()
&lt;&#x2F;span&gt;&lt;span&gt;    };
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;f2&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For traits we could imagine something similar as for functions. Supposing the
&lt;code&gt;default&lt;&#x2F;code&gt; keyword (specialization) could also be used for overloads; we could
imagine we could write something like this for an async version of
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;io&#x2F;trait.Read.html&quot;&gt;&lt;code&gt;Read&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The synchronous `Read` trait
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt; default &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Read {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The asynchronous `Read` trait
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt; async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;trait &lt;&#x2F;span&gt;&lt;span&gt;Read {
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Depending on how the traits are implemented, users could end up implementing
none, either, or both. Which variants of the trait are implemented could then be
highlighted through the docs, for example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;---------------------
&lt;&#x2F;span&gt;&lt;span&gt;Trait Implementations
&lt;&#x2F;span&gt;&lt;span&gt;---------------------
&lt;&#x2F;span&gt;&lt;span&gt;Debug
&lt;&#x2F;span&gt;&lt;span&gt;FromRawFd
&lt;&#x2F;span&gt;&lt;span&gt;Read
&lt;&#x2F;span&gt;&lt;span&gt;Read (async)
&lt;&#x2F;span&gt;&lt;span&gt;Write
&lt;&#x2F;span&gt;&lt;span&gt;Write (async)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This really is all a rough sketch. I don&#x27;t know whether using &lt;code&gt;default&lt;&#x2F;code&gt; as a
keyword would make sense here at all, or what the right way of highlighting this
in the docs are. What I hope to achieve with this is to share a glimpse of how
this could work end-to-end for Rust users. Docs, diagnostics, writing, and
consuming code are all different ways to experience the same feature. And I hope
this provides an idea of what an integration could possibly look like for both
library consumers and authors alike.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;potential-caveats&quot;&gt;Potential caveats&lt;&#x2F;h2&gt;
&lt;h4 id=&quot;backwards-incompatibility&quot;&gt;Backwards incompatibility&lt;&#x2F;h4&gt;
&lt;p&gt;As far as I can tell Rust doesn&#x27;t have anything yet that would preclude us from
going down this path. Indeed adding this would cause a delay in &quot;shipping&quot; async
Rust. But it would make it so we don&#x27;t need to effectively double the surface
area of the stdlib, which to me is worth it (this is coming from someone who&#x27;s
helped author an async copy of virtually every stdlib API).&lt;&#x2F;p&gt;
&lt;p&gt;If we decide this is worth exploring, the one thing we shouldn&#x27;t do is stabilize
&lt;code&gt;std::stream&lt;&#x2F;code&gt; before our explorations are over. I don&#x27;t believe any other APIs
are included yet in nightly which could pose an issue for async overloading, so
as long as we don&#x27;t stabilize that while we figure this out, we should be good!
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#stream&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;stream&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;And again, this is coming from someone who helped author the &lt;code&gt;Stream&lt;&#x2F;code&gt;
RFC, and added &lt;code&gt;Stream&lt;&#x2F;code&gt; to nightly. Please believe me that if someone wants to
stabilize async iterators, it&#x27;s me. But I think async overloading is the kind of
change we should consider and definitively rule out before proceeding we attempt
to stabilize the &lt;code&gt;Stream&lt;&#x2F;code&gt; API as-is.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h4 id=&quot;overloading-existing-stdlib-functions&quot;&gt;Overloading existing stdlib functions&lt;&#x2F;h4&gt;
&lt;p&gt;One issue to be aware of is that unlike Swift we cannot immediately fail if a
synchronous overload is selected in an async function. Rust&#x27;s async models
allows for delayed &lt;code&gt;.await&lt;&#x2F;code&gt;ing, which means we cannot error at the call-site.
Instead we&#x27;ll likely need to hook into the machinery that enables &lt;code&gt;#[must_use]&lt;&#x2F;code&gt;;
allowing us to validate whether the returned future is actually awaited — and
warn if it&#x27;s not. Even though this is slightly different from Swift appears to
do things, it should not present an insurmountable hurdle.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;feasibility-of-async-parity&quot;&gt;Feasibility of async parity&lt;&#x2F;h4&gt;
&lt;p&gt;One of the goals of the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.9.0&#x2F;async_std&#x2F;&quot;&gt;async-std&lt;&#x2F;a&gt;
project was to gauge the feasibility of creating a dual of the stdlib&#x27;s IO APIs
using async Rust. And two years in we can conclude it&#x27;s been an overwhelming
success: the only stdlib APIs we haven&#x27;t been able to faithfully reimplement in
async Rust are those which require async closures and async traits
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#async-closures-traits&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. But now that the Async Foundations WG is adding those
capabilities to the language, there are no blockers remaining for API parity
between sync and async Rust.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;async-closures-traits&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;An example of an API which requires async traits is
&lt;code&gt;async-std&lt;&#x2F;code&gt;&#x27;s
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.9.0&#x2F;async_std&#x2F;stream&#x2F;trait.Stream.html#method.collect&quot;&gt;&lt;code&gt;Stream::collect&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
We&#x27;ve managed to work around it, but had to box some items. An example of an API
which requires async closures is
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.9.0&#x2F;async_std&#x2F;stream&#x2F;trait.Stream.html#method.filter&quot;&gt;&lt;code&gt;Stream::filter&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
The callback provided to the method is not async right now because there&#x27;s no
way to express the lifetime of the borrowed item. But once we have async
closures this will become possible to express. Pretty much all differences
between std and async-std are minor issues like these, which we&#x27;re fairly
certain can be solved once Async Rust gains more capabilities.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h4 id=&quot;past-async-overloading-code-reuse&quot;&gt;Past async overloading: code reuse&lt;&#x2F;h4&gt;
&lt;p&gt;Finally, there&#x27;s an interesting question to ask whether it&#x27;s possible to reuse
code past an async overload. You could imagine a sync and an async parser
containing identical logic, except for the internal use of &lt;code&gt;.await&lt;&#x2F;code&gt;. To which
degree does Swift&#x27;s model limit code reuse? That should be something the async
WG should answer once it decides async overloading is indeed desireable, and
starts looking at ways it could be implemented.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;returning-impl-future-instead-of-async-fn&quot;&gt;Returning &lt;code&gt;impl Future&lt;&#x2F;code&gt; instead of &lt;code&gt;async fn&lt;&#x2F;code&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Without
&lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rfcs&#x2F;2515-type_alias_impl_trait.html&quot;&gt;TAIT&lt;&#x2F;a&gt;s &lt;code&gt;async fn&lt;&#x2F;code&gt;s cannot be named, and thus for the stdlib it&#x27;ll be desireable to return
manual futures from APIs instead. This means that we might want to write
something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;default &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;do_something_else&lt;&#x2F;span&gt;&lt;span&gt;() { ... }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;do_something_else&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; DoSomethingElse { ... }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;DoSomethingElse;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Future &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;DoSomethingElse { ... }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Luckily the compiler is aware of which traits are implemented on types, and
could validate that this indeed resolves to a valid async overload.
We should probably even make it so &lt;code&gt;-&amp;gt; impl Future&amp;lt;Output = io::Result&amp;lt;()&amp;gt;&amp;gt;&lt;&#x2F;code&gt;
works, but &lt;code&gt;-&amp;gt; io::Result&amp;lt;impl Future&amp;lt;Output = ()&amp;gt;&amp;gt;&lt;&#x2F;code&gt; does not. This would likely
be quicker to validate, and keep things feeling like &quot;async fn overloading&quot; only.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;overloads-for-other-effects&quot;&gt;Overloads for other effects&lt;&#x2F;h4&gt;
&lt;p&gt;A question which has come up is whether this mechanism could be used for other
effects as well. For example, it could be conceivable that in a &lt;code&gt;try fn&lt;&#x2F;code&gt; we
could expect to call a fallible API, while in a non-&lt;code&gt;try fn&lt;&#x2F;code&gt; we&#x27;d expect the
infallible method:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt; default &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;reserve&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;additional&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt; try &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;reserve&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;additional&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; throws ReserveError;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In my &lt;a href=&quot;&#x2F;fallible-iterator-adapters&#x2F;&quot;&gt;Fallible Iterator Adapter&lt;&#x2F;a&gt; post I pointed
out that we&#x27;re missing a fair number of fallible variants of existing APIs.
Boats has since authored &lt;a href=&quot;https:&#x2F;&#x2F;without.boats&#x2F;blog&#x2F;the-problem-of-effects&#x2F;&quot;&gt;The Problem of Effects in
Rust&lt;&#x2F;a&gt; which covers the
problem from a language perspective, and shows how if we introduced a different
kind of closure we could eliminate the need for &lt;code&gt;try_&lt;&#x2F;code&gt; iterator adapters.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;48043&quot;&gt;RFC 2116: Fallible Collection
Allocation&lt;&#x2F;a&gt; covers adding &lt;code&gt;try_&lt;&#x2F;code&gt;
variants of the base building blocks. But the implementation has decided not to add
&lt;code&gt;try_&lt;&#x2F;code&gt; variants for all allocation APIs since that would increase the API
surface too much. Which is a similar reasoning given for why we don&#x27;t have
fallible variants for all iterator APIs either.&lt;&#x2F;p&gt;
&lt;p&gt;The issues we&#x27;re covering in this post, Boats&#x27; effect post, and the issues in
RFC 2116 all seem related to each other. I don&#x27;t know if &quot;fallible overloading&quot;
could provide a partial way out of it, but maybe there&#x27;s something to it? The
possibilities different kinds of overloading could bring certainly are
interesting, and probably worth thinking about more.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;other&quot;&gt;Other&lt;&#x2F;h4&gt;
&lt;p&gt;There are two topics which I haven&#x27;t thought about, but should be thought about
by the working group:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;How does async overloading interact with &lt;code&gt;dyn Trait&lt;&#x2F;code&gt;?&lt;&#x2F;li&gt;
&lt;li&gt;How does async overloading interact with FFI?&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Basing on what I&#x27;ve seen come up in conversations there might be ways to make
this work, but it should be looked at more closely as part of a feasibility
probe.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Currently the async foundations roadmap does &lt;a href=&quot;https:&#x2F;&#x2F;nikomatsakis.github.io&#x2F;wg-async-foundations&#x2F;vision&#x2F;roadmap.html#slightly-past-the-horizon&quot;&gt;include a note on &quot;async
overloading&quot;&lt;&#x2F;a&gt;,
but it&#x27;s marked as &quot;slightly past the horizon&quot;. I think given this has
implications for async iteration, async IO, and every other async libs API, &lt;strong&gt;we
should make sure we&#x27;ve properly investigated async overloading before we make any
changes to the stdlib which would be incompatible with it.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To summarize what we&#x27;ve covered so far:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Async Rust is currently on a trajectory to doubling the API surface of IO
APIs in the stdlib.&lt;&#x2F;li&gt;
&lt;li&gt;Async overloading could provide a way out for us, enabling us to add async IO
APIs to the stdlib while keeping the number of IO APIs in the stdlib to its
current number.&lt;&#x2F;li&gt;
&lt;li&gt;As long as we don&#x27;t stabilize &lt;code&gt;Stream&lt;&#x2F;code&gt;, async IO traits, or any other async IO
types we should be capable of introducing async overloading without any
sharp edges.&lt;&#x2F;li&gt;
&lt;li&gt;Because async overloading informs the implementation of all of the async
types in the stdlib, investigating its feasiblity should be a priority for the
async WG.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;My hopes of this post is that it convinces folks that async overloading is an
idea worth taking seriously before we continue with any other designs. And to
perform a feasibility study whether this could actually work from a language,
libs, and compiler perspective.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Thanks to: Eric Holk, Irina Shestak, James Halliday, Scott McMurray, and Wesley
Wiser for helping review this post prior to publishing.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>optimizing hashmaps even more</title>
            <pubDate>Sat, 08 May 2021 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/optimizing-hashmaps-even-more/</link>
            <guid>https://blog.yoshuawuyts.com/optimizing-hashmaps-even-more/</guid>
            <description>&lt;p&gt;In our last post we took a look at possible ways we could improve the ergonomics
of Rust&#x27;s refcounting APIs. In this post we&#x27;ll be looking at Hashmap: how it&#x27;s
currently implemented, how we could optimize it further, and finally directions
we could explore to enable the compiler to automatically apply these optimizations.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;&#x2F;strong&gt; I&#x27;m not an expert. I&#x27;m not on any team involved with const
execution, nor do I hold any decision making power. This exists to share ideas
and curiosities of what might be possible in Rust in the spirit of sharing
posts with pals.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hashmaps-and-hashing-algorithms&quot;&gt;Hashmaps and hashing algorithms&lt;&#x2F;h2&gt;
&lt;p&gt;In 2017 Google introduced a new kind of hashmap for C++: &lt;a href=&quot;https:&#x2F;&#x2F;abseil.io&#x2F;blog&#x2F;20180927-swisstables&quot;&gt;the Swisstable
hashmap&lt;&#x2F;a&gt;. This structure uses SIMD
instructions to compute hashes, which is a great match for modern computer
hardware. So any improvements to the hashing algorithm would have an outsize
impact on performance, and in turn resource efficiency.&lt;&#x2F;p&gt;
&lt;p&gt;In the &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;ncHmEUmJZf4?t=210&quot;&gt;cppcon 2017 talk on Swisstable&lt;&#x2F;a&gt;,
the authors mention that across all of Google&#x27;s code, they found a non-trivial
amount of time was spent computing hashes &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#hashcount&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Amanieu&quot;&gt;Amanieu&lt;&#x2F;a&gt; from the libs team created a Rust variant
of the same algorithm for the
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;hashbrown&#x2F;&quot;&gt;Hashbrown&lt;&#x2F;a&gt; crate, which has since
become the default Hashmap implemention for Rust.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;hashcount&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;1% of CPU and 4% of RAM &lt;em&gt;of all of Google&#x27;s C++ code&lt;&#x2F;em&gt; is spent
doing things inside hashtables. Considering the scale of Google&#x27;s deployment,
the amount of CPU cycles spent is &lt;em&gt;enormous&lt;&#x2F;em&gt;. And it doesn&#x27;t even consider
software running on user devices such as Android and Chrome, or programming
languages other than C++.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;However we&#x27;ve known for a long time about a faster hashmap than Swisstable:
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Perfect_hash_function&quot;&gt;the perfect hashtable&lt;&#x2F;a&gt;.
The idea is that if you know all your keys ahead of time, you can create a lookup
table which never creates collisions, never has to re-index the hashmap, or grow
in size&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#hasher&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Though it&#x27;s not always possible to know all keys ahead of time, so
there are limits to when it can be used.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;hasher&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;There are a lot of considerations and tradeoffs for hashing
algorithms. &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;TartanLlama&#x2F;status&#x2F;1394635163972390914&quot;&gt;Sy Brand gave a brief overview on
Twitter&lt;&#x2F;a&gt; in reply to
this post.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Even so, let&#x27;s take a look at when it does make sense to use perfect
hashtables, and show examples of how to implement them.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;enums-as-keys&quot;&gt;enums as keys&lt;&#x2F;h2&gt;
&lt;p&gt;Imagine we&#x27;re building a protocol. The protocol has support for &quot;metadata&quot; and
&quot;body data&quot;. The metadata consists of keys and values. We could imagine its use
could look something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::collections::HashMap;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; metadata: HashMap&amp;lt;String, String&amp;gt; = HashMap::new();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;metadata.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;content_type&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(), &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;fast_proto&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;metadata.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;encryption_key&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(), generator.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next_key&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;metadata.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;content_fingerprint&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;bodyfingerprint&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;metadata.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;content_length&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;bodylength&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;request.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send_metadata&lt;&#x2F;span&gt;&lt;span&gt;(metadata).await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We create a hashmap, insert several key-value pairs into it, and finally
serialize it over the wire. Now imagine these are the &lt;em&gt;only&lt;&#x2F;em&gt; keys that are valid
to insert into the hashmap. Since we know all possible representations up
front, we could capture them within an enum:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::collections::HashMap;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;KeyName {
&lt;&#x2F;span&gt;&lt;span&gt;    ContentType,
&lt;&#x2F;span&gt;&lt;span&gt;    EncryptionKey,
&lt;&#x2F;span&gt;&lt;span&gt;    ContentFingerprint,
&lt;&#x2F;span&gt;&lt;span&gt;    ContentLength,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Display &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;KeyName { ... }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; metadata: HashMap&amp;lt;KeyName, String&amp;gt; = HashMap::new();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;metadata.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(KeyName::ContentType, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;fast_proto&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;metadata.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(KeyName::EncryptionKey, generator.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next_key&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;metadata.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(KeyName::ContentFingerprint, body.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;fingerprint&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;metadata.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(KeyName::ContentLength, body.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;request.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send_metadata&lt;&#x2F;span&gt;&lt;span&gt;(metadata).await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Because we&#x27;re using an enum we know all of our keys ahead of time &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#non_exhaust&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;,
and can simply &lt;code&gt;match&lt;&#x2F;code&gt; on the keys. Yet the code above will still expand to
&lt;a href=&quot;https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;fsEqPzaGM&quot;&gt;roughly 1200 lines of assembly&lt;&#x2F;a&gt;. This is
because the Rust compiler currently isn&#x27;t clever enough to lower the hashmap
into a lookup table.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;non_exhaust&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Yes yes, &lt;code&gt;#[non_exhaustive]&lt;&#x2F;code&gt; would change that. But we aren&#x27;t using
that here.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Now what would happen if we had a &quot;sufficiently smart compiler&quot;. The compiler
would be able to lower the hashmap to a fixed-sized array containing
&lt;code&gt;Option&amp;lt;String&amp;gt;&lt;&#x2F;code&gt; which uses &lt;code&gt;match&lt;&#x2F;code&gt; to access the data within &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#array&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;array&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;We may not always want to use an array to store the data. But we&#x27;re
dealing with a small key size here, so &lt;em&gt;it&#x27;s fine&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;HashMap {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;inner&lt;&#x2F;span&gt;&lt;span&gt;: [Option&amp;lt;String&amp;gt;; 4],
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;HashMap {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;: KeyName, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: String) -&amp;gt; Option&amp;lt;String&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; key {
&lt;&#x2F;span&gt;&lt;span&gt;            KeyName::ContentType =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;replace&lt;&#x2F;span&gt;&lt;span&gt;(value),
&lt;&#x2F;span&gt;&lt;span&gt;            KeyName::EncryptionKey =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;replace&lt;&#x2F;span&gt;&lt;span&gt;(value),
&lt;&#x2F;span&gt;&lt;span&gt;            KeyName::Fingerprint =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;replace&lt;&#x2F;span&gt;&lt;span&gt;(value),
&lt;&#x2F;span&gt;&lt;span&gt;            KeyName::ContentLength =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;replace&lt;&#x2F;span&gt;&lt;span&gt;(value),
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;: KeyName) -&amp;gt; Option&amp;lt;&amp;amp;String&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; key {
&lt;&#x2F;span&gt;&lt;span&gt;            KeyName::ContentType =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;            KeyName::EncryptionKey =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;            KeyName::Fingerprint =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;            KeyName::ContentLength =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What we&#x27;re seeing here is that we&#x27;ve replaced the hashing function with a
&lt;code&gt;match&lt;&#x2F;code&gt; statement. All data is stored within a fixed-sized array of &lt;code&gt;Option&lt;&#x2F;code&gt;s,
and each enum variant directly maps to one of the slots within array. This
removes the overhead of hashing entirely, and opens the door for further
optimizations (such as inlining).&lt;&#x2F;p&gt;
&lt;p&gt;Some might argue that: &quot;We could just write this code ourselves&quot;, but
writing custom data structures has costs associated with it: we need to realize
we need the structure in the first place, then write the structure, maintain it,
and teach everyone else working on the codebase about it. Even though it might
be faster than Rust&#x27;s default hashmap, going down this route has extra costs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;static-strings-as-keys&quot;&gt;static strings as keys&lt;&#x2F;h2&gt;
&lt;p&gt;In many ways our example of keying into a hashmap using an enum is a bit &lt;em&gt;too&lt;&#x2F;em&gt;
perfect. It assumes the author has awareness that their data is in fact
enumerable, and willingness to refactor the set of all keys into an enum. But it&#x27;s also
risky: what if want to add more keys later. What if those keys may not be
known during compilation? I personally often prefer to keep things simple when
I&#x27;m not sure how things might change in the future.&lt;&#x2F;p&gt;
&lt;p&gt;Code in the real world is often far less pristine. When trying to deliver a feature
under time pressure we&#x27;re often more focused on getting it working and tested, than
on performance. After all it&#x27;s usually &lt;em&gt;fast enough&lt;&#x2F;em&gt; anyway. We&#x27;ll often key into
hashmaps using strings, which have to be inlined into the created binary. The
assembly output for those inlined strings will look somewhat like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;.L__unnamed_1:
&lt;&#x2F;span&gt;&lt;span&gt;        .ascii  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;content_type&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;.L__unnamed_2:
&lt;&#x2F;span&gt;&lt;span&gt;        .ascii  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;encryption_key&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;.L__unnamed_3:
&lt;&#x2F;span&gt;&lt;span&gt;        .ascii  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;content_fingerprint&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;.L__unnamed_4:
&lt;&#x2F;span&gt;&lt;span&gt;        .ascii  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;content_length&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A compiler not only knows which strings are being inlined. It also knows which
strings are used as inputs to which methods. This is to say: a compiler is very
much capable of capturing the full set of inputs during compilation &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#llvm&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, which is
provides us with data not unlike a Rust enum. That means at least theoretically
it should be possible to generate a perfect hashmap for the following input:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;llvm&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;Not sure if this currently occurs in LLVM or not. But I know I&#x27;m able
to obtain this data through Salsa in Rust-Analyzer.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::collections::HashMap;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; metadata: HashMap&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static str&lt;&#x2F;span&gt;&lt;span&gt;, String&amp;gt; = HashMap::new();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;metadata.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;content_type&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;fast_proto&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;metadata.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;encryption_key&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, generator.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next_key&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;metadata.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;content_fingerprint&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, body.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;fingerprint&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;metadata.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;content_length&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, body.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;request.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send_metadata&lt;&#x2F;span&gt;&lt;span&gt;(metadata).await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And the generated perfect hashmap would be:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;HashMap {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;inner&lt;&#x2F;span&gt;&lt;span&gt;: [Option&amp;lt;String&amp;gt;; 4],
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;HashMap {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: String) -&amp;gt; Option&amp;lt;String&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; key {
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;content_type&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;replace&lt;&#x2F;span&gt;&lt;span&gt;(value),
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;encryption_key&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;replace&lt;&#x2F;span&gt;&lt;span&gt;(value),
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;content_fingerprint&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;replace&lt;&#x2F;span&gt;&lt;span&gt;(value),
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;content_length&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;replace&lt;&#x2F;span&gt;&lt;span&gt;(value),
&lt;&#x2F;span&gt;&lt;span&gt;            _ =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ std::hint::unreachable_unchecked() },
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;&amp;amp;String&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; key {
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;content_type&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;encryption_key&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;content_fingerprint&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;content_length&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;            _ =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ std::hint::unreachable_unchecked() },
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;hybrid-static-dynamic-keys&quot;&gt;hybrid static + dynamic keys&lt;&#x2F;h2&gt;
&lt;p&gt;If our keys are only ever known during runtime, we know the best hashmap we can
use is &lt;code&gt;Hashbrown&lt;&#x2F;code&gt;. But what if some of our keys are known during compilation?&lt;&#x2F;p&gt;
&lt;p&gt;This is where we can use a &quot;hybrid&quot; hashmap &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#hybrid&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;: we generate a lookup table for
the known keys, and use a regular hashmap as a fallback for all other keys. This
approach is used by &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hyperium&#x2F;http&quot;&gt;&lt;code&gt;hyperium&#x2F;http&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&#x27;s
&lt;code&gt;HeaderMap&lt;&#x2F;code&gt; struct. It keeps track of commonly used HTTP headers in a lookup
table, and falls back to a hashmap for all other headers.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;hybrid&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;I made up the term &quot;hybrid hashmap&quot; for the purpose of this post. Let me know
if you know of a term used in literature to describe this same structure.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Here&#x27;s a usage example of a hashmap which uses both dynamic and static data:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::collections::HashMap;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; metadata: HashMap&amp;lt;String, String&amp;gt; = HashMap::new();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;metadata.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;content_type&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(), &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;fast_proto&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;metadata.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;encryption_key&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(), generator.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next_key&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;metadata.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;gen_keyname&lt;&#x2F;span&gt;&lt;span&gt;(), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;gen_headername&lt;&#x2F;span&gt;&lt;span&gt;()); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; this generates values at runtime
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;request.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send_metadata&lt;&#x2F;span&gt;&lt;span&gt;(metadata).await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For this code we&#x27;re able to generate the following implementation. We create
a lookup table for our known keys, and fall back to a hashmap for all other keys:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;HashMap {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;inner&lt;&#x2F;span&gt;&lt;span&gt;: [Option&amp;lt;String&amp;gt;; 4],
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;: std::collections::HashMap&amp;lt;String, String&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;HashMap {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;: String, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: String) -&amp;gt; Option&amp;lt;String&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; key.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;content_type&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;replace&lt;&#x2F;span&gt;&lt;span&gt;(value),
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;encryption_key&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;replace&lt;&#x2F;span&gt;&lt;span&gt;(value),
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;content_fingerprint&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;replace&lt;&#x2F;span&gt;&lt;span&gt;(value),
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;content_length&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;replace&lt;&#x2F;span&gt;&lt;span&gt;(value),
&lt;&#x2F;span&gt;&lt;span&gt;            _ =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(key, value),
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Option&amp;lt;&amp;amp;String&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; key {
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;content_type&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;encryption_key&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;content_fingerprint&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;content_length&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.inner[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;            _ =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(key),
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A nice property about this approach is that if we only ever use known keys, we&#x27;ll get
speeds similar to that of a lookup table. It&#x27;s only once we start using custom keys
that we branch into a slower path and start allocating for the hashmap.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;looking-ahead&quot;&gt;Looking ahead&lt;&#x2F;h2&gt;
&lt;p&gt;While it&#x27;s possible for humans to look for instances where a hashmap can be
converted into a lookup table, for Rust only a compiler will be able to catch
&lt;em&gt;all&lt;&#x2F;em&gt; cases. This is because virtually no code in Rust is ever completely
self-contained.&lt;&#x2F;p&gt;
&lt;p&gt;Say we have a hashmap defined in crate A. And we have a crate B which
uses that hashmap. If B only ever uses A with static keys we&#x27;re able to optimize
for that use. However crate A will cannot know ahead of time what the usage
patterns of B will be like.&lt;&#x2F;p&gt;
&lt;p&gt;Add in more crates, transient wrappers, and legacy code - and it quickly becomes
clear why it&#x27;s ideal to let machines handle these kinds of optimizations.
However the question then becomes: how would we enable this in Rust?&lt;&#x2F;p&gt;
&lt;p&gt;I think if we had access to the following information during const &#x2F;
specialization we&#x27;d be able to create these kinds of optimizations:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Provide a way to enumerate all static inputs for a function.&lt;&#x2F;li&gt;
&lt;li&gt;Provide a way to tell if there are runtime inputs for a function.&lt;&#x2F;li&gt;
&lt;li&gt;Provide a way to count the number of invocations a function has within the
codebase.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;All of this information can be known by programmers ahead of time by reading
the code they&#x27;re working on. This means that a compiler can know this
information too. The question really is how (and where) to expose this
information.&lt;&#x2F;p&gt;
&lt;p&gt;My gut feeling is that we should be able to figure this out somewhere during
const evaluation and specialization &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#special&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#hasher&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Using an entirely made-up,
fantasy pseudo version of Rust I&#x27;d imagine we&#x27;d be able to create a new hashmap
using something like this:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;special&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;Yes I know that&#x27;s not a separate step, - less of a time, more of a place I guess.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;hasher&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;I don&#x27;t believe we can just specialize every hashmap + hasher combo.
I&#x27;m thinking we might be able to specialize Rust&#x27;s default hashmap though. As I understand it we
don&#x27;t guarantee much of anything other than it being fast and not being a DDoS
vector.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;this_is_a_specialization&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;create_hashmap&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;K: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;, V&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;m&lt;&#x2F;span&gt;&lt;span&gt;: Map&amp;lt;K, V&amp;gt;) -&amp;gt; HashMap {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; how often is this map&amp;#39;s `get` function called?
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;mem::invocation_count_of(m.get) == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; return stub structure because we know the data is never accessed
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; iterate over all static inputs provided to m.insert
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(k, _) in mem::static_inputs_of(m.insert) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; iterate over all keys and return a lookup table
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; count how often m.insert is called with non-static input
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;mem::dynamic_input_count_of(m.insert) != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; if there are runtime (non-static) arguments we want to return a hybrid hashmap
&lt;&#x2F;span&gt;&lt;span&gt;    } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; yay, return a lookup table
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Maybe there are other proposals in progress for const execution &#x2F; specialization
which cover these cases as well. Admittedly adding a bunch of new APIs backed by
&lt;code&gt;&#x2F;* compiler built-in *&#x2F;&lt;&#x2F;code&gt; is a bit of a cop-out, and I&#x27;d love to learn if there
could be ways to do the same which more closely integrate with what we already
have.&lt;&#x2F;p&gt;
&lt;p&gt;I hope this paints a rough picture of what I&#x27;m thinking. I wish I knew more
about the present and future of Rust&#x27;s const engine to design a better API. But
my goal with this post is less to propose something concrete, and more to convince
the right people this is something worth exploring. I hope in that regard
I&#x27;m doing alright so far (:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I hope everyone walks away from this post with two things: an understanding of
how to create a lookup table&#x2F;perfect hashmap in Rust, and excitement about a future
where our compilers can apply these optimizations for us.&lt;&#x2F;p&gt;
&lt;p&gt;The idea of transparently optimizing existing patterns based on usage is
fascinating to me. Usually when I think about these kinds of optimizations it&#x27;s
things like compilers optimizing math by converting it to bitwise instructions.
But imagine how cool it would be if we could optimize entire data structures
based on how they&#x27;re used. This type of optimization doesn&#x27;t need to stop with
hashmaps either: I got interested in this topic because I think we can optimize
channels significantly if we can inspect their use during compilation
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#channels&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;channels&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;&#x2F;sup&gt;
&lt;p&gt;For example: we could optimize an MPMC channel into a one-shot SPSC
channel if we know both the sender and receiver are never cloned, and only one
item is ever sent.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Another thing which excites me about this is that if we&#x27;re able to lower a
hashmap into a &lt;code&gt;match&lt;&#x2F;code&gt; statement, we can proceed to apply all optimizations we
use to match statements. This means optimizations such as removing unused enum
variants, reordering keys for quicker lookups, and even lowering the match
statement itself to more efficient structures such as prefix-tries. Rust&#x27;s
&lt;code&gt;match&lt;&#x2F;code&gt; performance is probably not where it could be yet either, and the more
we can express code of one kind in terms of another, the more impactful
optimizations can become.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks for reading!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>refcounts</title>
            <pubDate>Fri, 07 May 2021 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/refcounts/</link>
            <guid>https://blog.yoshuawuyts.com/refcounts/</guid>
            <description>&lt;p&gt;MyData I&#x27;ve wondered about for a while now is how to improve the ergonomics
of some of the structures in &lt;code&gt;std::sync&lt;&#x2F;code&gt;. There&#x27;s quite a bit of excitement
gathering about &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;ghost-cell&#x2F;0.2.1&#x2F;ghost_cell&#x2F;&quot;&gt;&lt;code&gt;ghost-cell&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
(and the &lt;a href=&quot;http:&#x2F;&#x2F;plv.mpi-sws.org&#x2F;rustbelt&#x2F;ghostcell&#x2F;&quot;&gt;paper&lt;&#x2F;a&gt;), and I figured
this would be as good a time as any to share some thoughts (questions?) on
ergonomics.&lt;&#x2F;p&gt;
&lt;p&gt;Like my last post, the intent of this post is less to provide a solution or
result of research, but instead share my current thinking on the topic. Rather
than asking questions in private, I figured I&#x27;d ask questions on here instead (:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;std-sync-barrier&quot;&gt;&lt;code&gt;std::sync::Barrier&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s use
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;sync&#x2F;struct.Barrier.html&quot;&gt;&lt;code&gt;std::sync::Barrier&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
to center our examples around. This is a data structure which enables synchronization between
any number of threads. One example of how you might want to use this is in an
HTTP server. You may want to create a connection to a database, connect to a
cache server, connect to perhaps some other backend, and only when all of those
have succeeded do you proceed to accept connections. If one of them takes a
while to initialize (or even fails entirely), our end-users won&#x27;t be impacted
because none of their requests are being handled yet.&lt;&#x2F;p&gt;
&lt;p&gt;This structure enables multiple threads to &lt;em&gt;synchronize&lt;&#x2F;em&gt; before starting work.
Its use usually looks something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::sync::{Arc, Barrier};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::thread;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; handles = Vec::with_capacity(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; barrier = Arc::new(Barrier::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;_ in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = Arc::clone(&amp;amp;barrier);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The same messages will be printed together.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; You will NOT see any interleaving.
&lt;&#x2F;span&gt;&lt;span&gt;    handles.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(thread::spawn(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span&gt;|| {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;before wait&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;        c.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;wait&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;after wait&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    }));
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Wait for other threads to finish.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; handle in handles {
&lt;&#x2F;span&gt;&lt;span&gt;    handle.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We create an instance of &lt;code&gt;Barrier&lt;&#x2F;code&gt; by passing it a count, wrap it in an &lt;code&gt;Arc&lt;&#x2F;code&gt;
(so it can be cloned), and then pass an instance of it to each thread. Important
to note is that the number of threads we spawn needs to &lt;em&gt;exactly&lt;&#x2F;em&gt; line up to the
number we&#x27;ve apssed into &lt;code&gt;Barrier::new&lt;&#x2F;code&gt;. If the number is too high our
application will lock up and never continue. If the number is too low, the
application will start before all threads are ready, defeating the point of
using the structure in the first place.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;dynamic-barrier&quot;&gt;dynamic Barrier&lt;&#x2F;h2&gt;
&lt;p&gt;One difficulty with &lt;code&gt;std::sync::Barrier&lt;&#x2F;code&gt; is that we need to &lt;em&gt;statically&lt;&#x2F;em&gt; pass
the number in. This means in order to create the synchronization structure we
need to know up front how many items we&#x27;re trying to synchronize. Say we&#x27;re
dealing with an iterator of unknown length, and we want to exhaust all items
before continuing? We don&#x27;t know the number up front, so we can&#x27;t use the
structure:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::thread;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::sync::{Arc, Barrier};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;from_iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;: impl Iterator&amp;lt;Item = MyData&amp;gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; handles = Vec::new();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; barrier = Arc::new(Barrier::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;* ??? *&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; item in iter {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ... create a thread and wait within
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ... join all handles
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Counting at runtime is not something exceptional though. In our example &lt;code&gt;Arc&lt;&#x2F;code&gt;
works entirely at runtime, making work without passing a count ahead of time.
Though we don&#x27;t have a dynamic version of &lt;code&gt;Barrier&lt;&#x2F;code&gt; in the stdlib, we &lt;em&gt;do&lt;&#x2F;em&gt; have
one in the ecosystem in the form of:
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;crossbeam&#x2F;0.8.0&#x2F;crossbeam&#x2F;sync&#x2F;struct.WaitGroup.html&quot;&gt;&lt;code&gt;crossbeam::sync::WaitGroup&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
With it we can rewrite our previous example like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::thread;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;crossbeam::sync::WaitGroup;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;from_iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;: impl Iterator&amp;lt;Item = MyData&amp;gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; handles = Vec::new();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; wg = WaitGroup::new();    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 1. create a new instance.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; item in iter {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; wg = wg.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;();      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 2. clone it
&lt;&#x2F;span&gt;&lt;span&gt;        handles.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(thread::spawn(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move&lt;&#x2F;span&gt;&lt;span&gt;|| {
&lt;&#x2F;span&gt;&lt;span&gt;            println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;before wait&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;            wg.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;wait&lt;&#x2F;span&gt;&lt;span&gt;();            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 3. wait to sync
&lt;&#x2F;span&gt;&lt;span&gt;            println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;after wait&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;        }));
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    wg.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;wait&lt;&#x2F;span&gt;&lt;span&gt;();                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; 4. also sync our original wg instance
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ... join all handles
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The upside of using &lt;code&gt;WaitGroup&lt;&#x2F;code&gt; over &lt;code&gt;Barrier&lt;&#x2F;code&gt; is that it&#x27;s much easier to use,
and more widely applicable. The downside is that it&#x27;s (marginally) less efficient
since we need to count the instances at runtime rather than having that
information up front &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#precision&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;precision&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;One could argue that manually passing the count up front can be an
extra safeguard - but there&#x27;s inherent risks to mis-counting the number of
instances. So I&#x27;m not sure that&#x27;s much of an extra safeguard. More on that later.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;I don&#x27;t want to argue for including &lt;code&gt;WaitGroup&lt;&#x2F;code&gt; in the stdlib since it&#x27;s unclear
how common the use of &lt;code&gt;Barrier&lt;&#x2F;code&gt; is. But I hope to have illustrated that
&lt;code&gt;Barrier&lt;&#x2F;code&gt; has limitations in how it can be used to create cross-thread
synchronization points.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;const-barrier&quot;&gt;const Barrier&lt;&#x2F;h2&gt;
&lt;p&gt;As we&#x27;ve seen in the first example there&#x27;s another issue: we need to ensure that
the number passed to &lt;code&gt;Barrier::new&lt;&#x2F;code&gt; matches the number of threads we spawn. One
way we could fix this is by creating a variable, and passing that same variable
to both the loop and &lt;code&gt;Barrier::new&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; count = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; handles = Vec::new();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; barrier = Arc::new(Barrier::new(count));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;_ in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..count {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = Arc::clone(&amp;amp;barrier);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;* ... *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This definitely works, but it still manually requires synchronizing the value in
&lt;code&gt;Barrier&lt;&#x2F;code&gt; and the value in the loop. Even though it&#x27;s more efficient than using
&lt;code&gt;WaitGroup&lt;&#x2F;code&gt;, it&#x27;s less ergonomic to use. However if we, as humans, look at the
code it&#x27;s immediately clear what the value in &lt;code&gt;Barrier::new&lt;&#x2F;code&gt; should be. Namely:
we&#x27;re calling &lt;code&gt;Arc::clone&lt;&#x2F;code&gt; ten times, so we know &lt;em&gt;ahead of time&lt;&#x2F;em&gt; that the value
we pass to &lt;code&gt;Barrier::new&lt;&#x2F;code&gt; should be &lt;code&gt;10&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now here&#x27;s what I wonder (and honestly, am not sure about). Given the number of
clones can be statically inferred by humans by looking at the code, could we
find a way to for this information to become statically available during &lt;code&gt;const&lt;&#x2F;code&gt;?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; count = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; handles = Vec::new();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; barrier = Barrier::new()
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;_ in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..count {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = barrier.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;* ... *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That would allow us to create a dynamic barrier and compile-time barrier with
similar APIs, but different assurances. The dynamic barrier would be more
flexible and work for unknown inputs, and the compile-time barrier would be more
efficient, but only work if the number of items is known at compile-time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Using &lt;code&gt;std::sync::Barrier&lt;&#x2F;code&gt; only acts an example. The same reasoning could be
applied to e.g. &lt;code&gt;Arc&lt;&#x2F;code&gt;, &lt;code&gt;Rc&lt;&#x2F;code&gt;, &lt;code&gt;channel&lt;&#x2F;code&gt;, and more. For example for channels it
could be interesting if we could compute ahead of time what the max number of
items that might be in flight are, and fill that in as the queue size. Caveats
and circumstances apply, but the general premise is: &lt;em&gt;&quot;If some item count is
known at compile time, is there a way we can pass that number back to our
structures?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Crates such as &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;static-rc&#x2F;0.3.1&#x2F;static_rc&#x2F;&quot;&gt;&lt;code&gt;static_rc&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; are
getting close to this idea, but still require manually passing in the count. I&#x27;m
wondering whether it could be possible to eliminate that count entirely.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;edit&lt;&#x2F;strong&gt;: I found &lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;n420cg&#x2F;is_it_possible_to_write_overheadfree_cyclic&#x2F;&quot;&gt;this
thread&lt;&#x2F;a&gt;
by the author of &lt;code&gt;static_rc&lt;&#x2F;code&gt; which asks very similar questions as we do here.
Also &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;lcnr7&#x2F;status&#x2F;1390653250383355904&quot;&gt;lcnr shared some thoughts on Twitter about the feasibility&lt;&#x2F;a&gt; of what refcounting in const.&lt;&#x2F;p&gt;
&lt;p&gt;Before closing out this post, I want to re-iterate once more that nothing of
this is a concrete proposal. I&#x27;m not even advocating for including
&lt;code&gt;crossbeam::sync::WaitGroup&lt;&#x2F;code&gt; in the stdlib. The purpose of this post is to share
thinking, and ask questions about what is desireable and possible within the
(future of) the Rust language.&lt;&#x2F;p&gt;
&lt;p&gt;And with that, thanks so much for reading this - happy weekend!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Futures Concurrency Notes: join and const-eval</title>
            <pubDate>Sat, 16 Jan 2021 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/future-join-and-const-eval/</link>
            <guid>https://blog.yoshuawuyts.com/future-join-and-const-eval/</guid>
            <description>&lt;p&gt;Happy new year everyone! Today we&#x27;re trying something new: less of a blog
post, more of &lt;em&gt;research notes&lt;&#x2F;em&gt;. This is less of a &quot;here&#x27;s something I&#x27;ve
concluded&quot;, and more of: &quot;here&#x27;s something I&#x27;m thinking about&quot;. Today&#x27;s topic
is: &quot;How can we add &lt;code&gt;Future::{try_}join&lt;&#x2F;code&gt; and &lt;code&gt;{try_}join!&lt;&#x2F;code&gt; to the stdlib in a
way that feels consistent?&quot;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-does-joining-futures-do&quot;&gt;What does joining Futures do?&lt;&#x2F;h2&gt;
&lt;p&gt;A Future in Rust is best though of as a &quot;value which eventually becomes
available&quot;. It&#x27;s not specified &lt;em&gt;when&lt;&#x2F;em&gt; a value becomes available, so using
&lt;code&gt;.await&lt;&#x2F;code&gt; allows us to wait for it until it&#x27;s available.&lt;&#x2F;p&gt;
&lt;p&gt;Sometimes we want to wait on more than one future at the time: after all,
when we&#x27;re waiting on things, we can do other things in the mean time. And
one way to do this is by calling &lt;code&gt;join&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;async-std&lt;&#x2F;code&gt; exposes a &lt;code&gt;Future::join&lt;&#x2F;code&gt; method, and &lt;code&gt;async-macros&lt;&#x2F;code&gt; exposes a
&lt;code&gt;join!&lt;&#x2F;code&gt; macro. An example joining two futures:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(join!(a, b).await, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(b).await, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However once we start joining more than two futures, the output types become
different:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(join!(a, b, c).await, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(b).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(c).await, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;)));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see, each invocation of &lt;code&gt;Future::join&lt;&#x2F;code&gt; returns a tuple. But that
means that chaining calls to it starts to nest tuples, which becomes hard to
use. And it becomes more nested the more times you chain. Oh no!&lt;&#x2F;p&gt;
&lt;p&gt;In contrast, the &lt;code&gt;join!&lt;&#x2F;code&gt; macro dynamically grows the number of items returned
in the tuple. This is possible because macros have loops, and can just write
code -- so inside the macro we just expand the output to a tuple which is
large enough to hold all of the outputs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-does-join-return&quot;&gt;What does &lt;code&gt;join!&lt;&#x2F;code&gt; return?&lt;&#x2F;h2&gt;
&lt;p&gt;The definition of &lt;code&gt;async_macros::join!&lt;&#x2F;code&gt; is fairly brief, so I&#x27;ll just share
it right here. The only detail missing is the defition of the &lt;code&gt;MaybeDone&lt;&#x2F;code&gt;
type: it&#x27;s a wrapper which can be awaited, and stores the output type of the
future once it completes. We wait for all instances of &lt;code&gt;MaybeDone&lt;&#x2F;code&gt; to
complete, and at the end we take all their values and return it from the
future:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;macro_export&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;macro_rules! &lt;&#x2F;span&gt;&lt;span&gt;join {
&lt;&#x2F;span&gt;&lt;span&gt;    ($(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$fut&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;ident&lt;&#x2F;span&gt;&lt;span&gt;),* $(,)?) =&amp;gt; { {
&lt;&#x2F;span&gt;&lt;span&gt;        async {
&lt;&#x2F;span&gt;&lt;span&gt;            $(
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Move future into a local so that it is pinned in one place and
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; is no longer accessible by the end user.
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$fut &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$crate&lt;&#x2F;span&gt;&lt;span&gt;::MaybeDone::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$fut&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;            )*
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$crate&lt;&#x2F;span&gt;&lt;span&gt;::utils::poll_fn(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;|cx| {
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$crate&lt;&#x2F;span&gt;&lt;span&gt;::utils::future::Future;
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$crate&lt;&#x2F;span&gt;&lt;span&gt;::utils::task::Poll;
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$crate&lt;&#x2F;span&gt;&lt;span&gt;::utils::pin::Pin;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; all_done = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;                $(
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; fut = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Pin::new_unchecked(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$fut&lt;&#x2F;span&gt;&lt;span&gt;) };
&lt;&#x2F;span&gt;&lt;span&gt;                    all_done &amp;amp;= Future::poll(fut, cx).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_ready&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;                )*
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; all_done {
&lt;&#x2F;span&gt;&lt;span&gt;                    Poll::Ready(($(
&lt;&#x2F;span&gt;&lt;span&gt;                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Pin::new_unchecked(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$fut&lt;&#x2F;span&gt;&lt;span&gt;) }.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;                    )*))
&lt;&#x2F;span&gt;&lt;span&gt;                } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;                    Poll::Pending
&lt;&#x2F;span&gt;&lt;span&gt;                }
&lt;&#x2F;span&gt;&lt;span&gt;            }).await
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    } }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see the outer-most value returned is an &lt;code&gt;async {}&lt;&#x2F;code&gt; block. This
isn&#x27;t a specific type, but can be referred to using &lt;code&gt;impl Future&lt;&#x2F;code&gt;. However
the type returned by &lt;code&gt;Future::join&lt;&#x2F;code&gt; is a concrete &lt;code&gt;Join&lt;&#x2F;code&gt; future. This type
&lt;em&gt;can&lt;&#x2F;em&gt; be addressed by name, and actually passed around.&lt;&#x2F;p&gt;
&lt;p&gt;However as we chain &lt;code&gt;Future::join&lt;&#x2F;code&gt; repeatedly, the resulting future&#x27;s
signature will look somewhat like: &lt;code&gt;Join&amp;lt;Join&amp;lt;Join&amp;lt;Join&amp;lt;T&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;&#x2F;code&gt;. This is not
great.&lt;&#x2F;p&gt;
&lt;p&gt;So on the one hand we have anonymous futures which can only be addressed
through &lt;code&gt;impl Future&lt;&#x2F;code&gt;. And on the other hand we have deeply nested futures
which are a pain to write by hand. Can we do better?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;consistent-return-types&quot;&gt;consistent return types&lt;&#x2F;h2&gt;
&lt;p&gt;One thing I mentioned at the start but didn&#x27;t dive in yet is the fact that
we&#x27;d like to align the return types of &lt;code&gt;join!&lt;&#x2F;code&gt; and &lt;code&gt;Future::join&lt;&#x2F;code&gt;. Even if
&lt;code&gt;Future::join&lt;&#x2F;code&gt; would only ever take one other future as an argument, being
able to switch between the method and the macro without needing to change the
signature of the returned types is a a huge bonus.&lt;&#x2F;p&gt;
&lt;p&gt;After having worked on &lt;code&gt;async-std&lt;&#x2F;code&gt; for the past two years where a lot of APIs
use &lt;code&gt;async fn&lt;&#x2F;code&gt;, I&#x27;m now somewhat convinced that the stdlib should &lt;em&gt;never&lt;&#x2F;em&gt; do
this. Which you can see reflected in APIs such as &lt;code&gt;std::future::ready&lt;&#x2F;code&gt; which
now returns the concrete future &lt;code&gt;std::future::Ready&lt;&#x2F;code&gt;, whereas in &lt;code&gt;async-std&lt;&#x2F;code&gt;
it was just an &lt;code&gt;async fn&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Probably another point worth touching on is the &lt;code&gt;futures-rs&lt;&#x2F;code&gt; implementation
of &lt;code&gt;join!&lt;&#x2F;code&gt;. This doesn&#x27;t return any kind of future at all, wrapping the
&lt;code&gt;.await&lt;&#x2F;code&gt; call within the macro instead. I feel somewhat strongly that
&lt;code&gt;.await&lt;&#x2F;code&gt; calls shouldn&#x27;t be hidden in code, but instead always be visible.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Example of futures_rs::join!
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(join!(a, b), (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; is this sync or async?
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This slight digression into &lt;code&gt;futures-rs&lt;&#x2F;code&gt; aside, I think if we were to add
&lt;code&gt;future::Future::join&lt;&#x2F;code&gt; and &lt;code&gt;future::join!&lt;&#x2F;code&gt; functions to the stdlib, both
should be returning concrete futures. And because they effectively do the
same thing, we should make it so they both return the same &lt;code&gt;Join&lt;&#x2F;code&gt; type.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;maybe-const-can-help&quot;&gt;Maybe const can help?&lt;&#x2F;h2&gt;
&lt;p&gt;So the question now becomes: &quot;how can we do this?&quot;. And I think the answer
for this is: &quot;const tuples may be able to help&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;So const tuples don&#x27;t exist in Rust today yet. Not even on nightly. The only
way to create variadic tuples is through macros like we&#x27;ve shown. However
from talking to members of the const-eval WG const tuples are definitely on
the roadmap, though it may take a while. However now that we&#x27;re seeing a move
to fund more people to work on the compiler, I&#x27;m hoping that this may be
possible within a few years, which isn&#x27;t &lt;em&gt;that&lt;&#x2F;em&gt; long in the grand scheme of
things.&lt;&#x2F;p&gt;
&lt;p&gt;Given there&#x27;s no proposal for const tuples, it&#x27;s hard to write an example
since I have no clue what the syntax for it will be. For N-length arrays the
syntax is the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;array_windows&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; N: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; ArrayWindows&amp;lt;&amp;#39;_, T, N&amp;gt;;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;const N: usize&lt;&#x2F;code&gt; here is the length argument for the array of type &lt;code&gt;T&lt;&#x2F;code&gt;.
The operations this function returns are on &lt;code&gt;[T; N]&lt;&#x2F;code&gt;. However tuples don&#x27;t
have a consistent type &lt;code&gt;T&lt;&#x2F;code&gt;; values contained within tuples are heterogenous.
So a tuple of length &lt;code&gt;N&lt;&#x2F;code&gt; can contain &lt;code&gt;N&lt;&#x2F;code&gt; different types. I have no clue how
this would be expressed in &lt;code&gt;const&lt;&#x2F;code&gt; contexts (if at all possible?).&lt;&#x2F;p&gt;
&lt;p&gt;So for now let&#x27;s just pretend we can define N-length tuples &lt;em&gt;inside&lt;&#x2F;em&gt; function
signatures, and cross our fingers that this makes enough sense that the idea
comes across. Assuming something like that would work, I would expect
&lt;code&gt;Future::Join&lt;&#x2F;code&gt; to be able to defined along these lines:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Future {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Join with one other future.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;F: Future&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;other&lt;&#x2F;span&gt;&lt;span&gt;: F) -&amp;gt; Join&amp;lt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;, F)&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This signature tries to convey: this future holds at least two futures:
&lt;code&gt;Self&lt;&#x2F;code&gt;, and another future we&#x27;re joining with. For the &lt;code&gt;join!&lt;&#x2F;code&gt; macro we could
fill out the types using code generation, populating the values of the tuple
at compile time. Invoking it would yield the following return type:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; fut = join!(a, b);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; fut: Join&amp;lt;(Ready&amp;lt;Output = u8&amp;gt;, Ready&amp;lt;Output = u8&amp;gt;)&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; fut = join!(a, b, c);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; fut: Join&amp;lt;(Ready&amp;lt;Output = u8&amp;gt;, Ready&amp;lt;Output = u8&amp;gt;, Ready&amp;lt;Output = u8&amp;gt;)&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Assuming once we have const tuples we&#x27;ll also have const panic, we can guard
against the case where zero futures are provided to &lt;code&gt;Join&lt;&#x2F;code&gt;. Or perhaps the
signature should instead be:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;Join&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;, (Other, Other2)&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The details are unclear, because well, I don&#x27;t know how this should work in
the future. Maybe there&#x27;s a different feature a play here too: what if
expressing this in signatures actually requires &lt;code&gt;const-variadics&lt;&#x2F;code&gt; or
something. This may actually be relying on a variety of features I&#x27;m not
tracking.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-does-that-mean-for-adding-futures-concurrency-to-the-stdlib&quot;&gt;What does that mean for adding futures concurrency to the stdlib?&lt;&#x2F;h2&gt;
&lt;p&gt;This post is rooted in research I was doing exactly to answer that question.
&lt;code&gt;join!&lt;&#x2F;code&gt; and &lt;code&gt;Future::join&lt;&#x2F;code&gt; feel like they do exactly what they should, module
some issues around their return types. Unfortunately however it seems the
best solution would require a const-eval feature that doesn&#x27;t even have an
RFC yet.&lt;&#x2F;p&gt;
&lt;p&gt;Given I expect Rust to stick around for at least a few more decades, and how
core this functionality is for async programming. I think it&#x27;s actually worth
waiting to implement these features correctly, rather than rushing to add
them in the short term. Libraries such as &lt;code&gt;async-std&lt;&#x2F;code&gt; and &lt;code&gt;async-macros&lt;&#x2F;code&gt; can
provide suitable solutions through user space in the interim.&lt;&#x2F;p&gt;
&lt;p&gt;In addition to that, there&#x27;s one more feature in the language required before
we can consider adding &lt;code&gt;Future::join&lt;&#x2F;code&gt;: namely, we need either
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;64797&quot;&gt;&lt;code&gt;#[cfg(accessible)]&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, or
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;64796&quot;&gt;&lt;code&gt;#[cfg(version)]&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. This is
currently a blocker to adding &lt;em&gt;any&lt;&#x2F;em&gt; method on the &lt;code&gt;Future&lt;&#x2F;code&gt; trait. Since the
majority of the async ecosystem relies on &lt;code&gt;Ext&lt;&#x2F;code&gt; traits to implement missing
functionality, adding a method of the same name to the stdlib would cause
ambiguity. So in order to prevent accidental ecosystem breakage, libraries
outside of std should gain the ability to detect whether a method has been
implemented in the stdlib. Which is what &lt;code&gt;accessible&lt;&#x2F;code&gt; and &lt;code&gt;version&lt;&#x2F;code&gt; are for.&lt;&#x2F;p&gt;
&lt;p&gt;However one possibility may be that we add &lt;code&gt;join!&lt;&#x2F;code&gt; based on the &lt;code&gt;async {}&lt;&#x2F;code&gt;
block implementation in the near term without adding &lt;code&gt;Future::join&lt;&#x2F;code&gt; as well.
That would at least allow us to expose that funcionality from the stdlib,
even if in some instances it may not be the most ergonomic.&lt;&#x2F;p&gt;
&lt;p&gt;Then later on, once we gain the ability to reason about tuples&#x2F;variadics in
const contexts, we can switch the return type to be &lt;code&gt;Join&lt;&#x2F;code&gt;, and add the
&lt;code&gt;Future::join&lt;&#x2F;code&gt; method as well. That way we get a solution in the short term,
but still do the right thing in the long term. This depends on &lt;code&gt;async {}&lt;&#x2F;code&gt;
being forward compatible with returning a concrete future though. I&#x27;m not
sure if this has been done before, and the lang team might need to weigh in
on that.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;edit (2020-01-17):&lt;&#x2F;strong&gt; As pointed out &lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;kyjprs&#x2F;blog_post_futurejoin_and_consteval&#x2F;gjhb50a&#x2F;?utm_source=reddit&amp;amp;utm_medium=web2x&amp;amp;context=3&quot;&gt;here&lt;&#x2F;a&gt;
by matthieum, if we had a variadic &lt;code&gt;Join&lt;&#x2F;code&gt; type, there&#x27;s no reason we couldn&#x27;t
implement &lt;code&gt;join&lt;&#x2F;code&gt; on tuples directly.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Tuple::join
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!((a, b, c).await, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Array::join
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!([a, b, c].await, [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This would soft-deprecate the need to use &lt;code&gt;future::join!&lt;&#x2F;code&gt; and could probably
also be extended to arrays and slices of futures too &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#join_all&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. The question is
whether the same &lt;code&gt;Join&lt;&#x2F;code&gt; type could be used for all implementations, since it
wouldn&#x27;t return a tuple but an array or vec instead. This can probably only
be answered once designs for the corresponding language features start.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;join_all&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;code&gt;join!&lt;&#x2F;code&gt; on an array is effectively an instance of
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.3.12&#x2F;futures&#x2F;future&#x2F;fn.join_all.html&quot;&gt;&lt;code&gt;join_all!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
In my designs I&#x27;ve mostly relegated &lt;code&gt;join_all!&lt;&#x2F;code&gt; as not being a primitive,
instead favoring designs such as &lt;code&gt;TaskGroup&lt;&#x2F;code&gt; and &lt;code&gt;ParallelStream&lt;&#x2F;code&gt; for a
collection of N futures since these more often than not will want to be run
on a executor anyway. However wanting to join N futures is still nice to be
able to do, and implementing &lt;code&gt;Array::join&lt;&#x2F;code&gt; may very well provide a way for us
to do so.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;other-considerations&quot;&gt;Other considerations&lt;&#x2F;h2&gt;
&lt;p&gt;Everything we&#x27;ve expressed here not only applies to &lt;code&gt;future::Future::Join&lt;&#x2F;code&gt;
and &lt;code&gt;future::join!&lt;&#x2F;code&gt;. It applies to the &lt;code&gt;try_join&lt;&#x2F;code&gt;, &lt;code&gt;race&lt;&#x2F;code&gt;, and &lt;code&gt;try_race&lt;&#x2F;code&gt;
variants as well. The
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.9.0&#x2F;async_std&#x2F;future&#x2F;index.html&quot;&gt;&lt;code&gt;async_std::future&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
docs explain how these types cover the full range of awaiting futures.&lt;&#x2F;p&gt;
&lt;p&gt;Additionally the &lt;code&gt;future::join&lt;&#x2F;code&gt; variants only really work well when you know
ahead of time how many futures you&#x27;re going to be awaiting. If the number is
dynamic, other constructs should be used. In a future post I may talk about
&lt;code&gt;TaskGroup&lt;&#x2F;code&gt;, an adaptation of &lt;code&gt;crossbeam::scope&lt;&#x2F;code&gt; I&#x27;m working on, inspired by
Swift&#x27;s upcoming &lt;code&gt;task&lt;&#x2F;code&gt; proposal. But other constructs like &lt;code&gt;parallel-stream&lt;&#x2F;code&gt;
and &lt;code&gt;FuturesUnordered&lt;&#x2F;code&gt; already exist as well.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve looked at what it would take to add &lt;code&gt;Future::join&lt;&#x2F;code&gt; and
&lt;code&gt;join!&lt;&#x2F;code&gt; to the stdlib where both functions would return the same, named
future. One plausible way to achieve this would be through const tuples (and
possible const variadics, which may or may not be the same thing).&lt;&#x2F;p&gt;
&lt;p&gt;However it may be possible to add &lt;code&gt;future::join!&lt;&#x2F;code&gt; in the near term, and once
Rust gains the appropriate language features add &lt;code&gt;Future::join&lt;&#x2F;code&gt; and upgrade
&lt;code&gt;join!&lt;&#x2F;code&gt; to use the same &lt;code&gt;Join&lt;&#x2F;code&gt; future. This would enable adding the
functionality in the near term, but still achieving the ideal design later
on.&lt;&#x2F;p&gt;
&lt;p&gt;This post is a bit of an experiment: single draft, Saturday morning writing.
I&#x27;ve been doing a lot of research into stabilizing async Rust paradigms
recently, and figured I&#x27;d share some of the findings along the way. In part
for my own reference. But also to communicate needs async Rust may have to
members of other Rust teams.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, hope you enjoyed this, and hope you have a good weekend!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;If you or your company like the work I&#x27;m doing, you&#x27;re welcome to support
me through &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yoshuawuyts&quot;&gt;GitHub sponsors&lt;&#x2F;a&gt;. Special thanks
to my sponsors: &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hibbian&quot;&gt;hibbian&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;milesgranger&quot;&gt;milesgranger&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;romatthe&quot;&gt;romatthe&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;No9&quot;&gt;No9&lt;&#x2F;a&gt;, and
several others who prefer to remain anonymous.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Rust 2021</title>
            <pubDate>Thu, 24 Sep 2020 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/rust-2021/</link>
            <guid>https://blog.yoshuawuyts.com/rust-2021/</guid>
            <description>&lt;p&gt;I am tired. Today was rough. This year has been rough. Everyone around me is
tired too. 2020 has been a hot mess, coming right after a not so hot 2019,
and a messy 2018. It&#x27;s not just you. It&#x27;s everything. It&#x27;s okay.&lt;&#x2F;p&gt;
&lt;p&gt;My wish for Rust 2021 is for you to go easy on yourself. No really. You. If
you&#x27;ve done any work on Rust at all, that means you doubly so. Yes
&lt;em&gt;really&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The core team has tasked themselves with &lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;2020&#x2F;08&#x2F;18&#x2F;laying-the-foundation-for-rusts-future.html&quot;&gt;starting a
foundation&lt;&#x2F;a&gt;.
Laudible, but can we take a sec to realize we&#x27;re still mid-pandemic. Not that
long ago our biggest sponsor cut back drastically. People lost their jobs.
Co-workers. Friends. People we love and cherish. Things are tough. And
there&#x27;s still &lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;2020&#x2F;06&#x2F;04&#x2F;Rust-1.44.0.html&quot;&gt;much&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;2020_Belarusian_protests&quot;&gt;much&lt;&#x2F;a&gt;, much more.
And right while all this is happening we&#x27;re creating this foundation. Ooph.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s why I want the core team to take a break. Go on a vacation. Close the
office for a while. I don&#x27;t know when. Maybe do one in the winter. Maybe one
in summer, after we have a foundation. Big ol&#x27; summer vacation. Too hot to
think anyway.&lt;&#x2F;p&gt;
&lt;p&gt;Actually not just the core team: I want everyone to take a vacation. The
whole Rust project. Hit the brakes, take it easy. Archive &lt;code&gt;rust-lang&#x2F;rust&lt;&#x2F;code&gt;
for a week. Can&#x27;t come to work if the office is locked. Take a breath. Take a
bath.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Rust&quot; is the outcome of the processes we apply. It&#x27;s through dialog, labor,
and mutual respect that we get any of this done. And we can&#x27;t do these things
if we can&#x27;t talk about how we feel. And uhh, reading the room here, but
people don&#x27;t seem to be doing well. How can we feel safe in dialog if we
don&#x27;t even feel physically safe. We really gotta take care of ourselves first
before we take care of RFC2000.&lt;&#x2F;p&gt;
&lt;p&gt;Of course we also &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;nnethercote&#x2F;status&#x2F;1308958853417979904&quot;&gt;should find ways to get
paid&lt;&#x2F;a&gt;. Of course
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;project-portable-simd&quot;&gt;stdsimd&lt;&#x2F;a&gt; is cool, and
&lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;inside-rust&#x2F;2020&#x2F;09&#x2F;18&#x2F;error-handling-wg-announcement.html&quot;&gt;error
handling&lt;&#x2F;a&gt;
is cool, and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;wg-async-foundations&quot;&gt;async&lt;&#x2F;a&gt; is
cool, and…&lt;&#x2F;p&gt;
&lt;p&gt;Yea.&lt;&#x2F;p&gt;
&lt;p&gt;The backlog of things to work on is infinite. The people that work on them
aren&#x27;t. The cool problems to work on will be here when we come back. I just
hope you&#x27;ll still be here with me ♥&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Async Iteration I: Iteration Semantics</title>
            <pubDate>Fri, 18 Sep 2020 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/async-iteration/</link>
            <guid>https://blog.yoshuawuyts.com/async-iteration/</guid>
            <description>&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;This post is part of the Async Iteration series:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-iteration&#x2F;&quot;&gt;Async Iteration I: Semantics&lt;&#x2F;a&gt; (this post)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-iterator-crate&#x2F;&quot;&gt;Async Iteration II: Async Iterator Crate&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-iterator-trait&quot;&gt;Async Iteration III: Async Iterator Trait&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;In a &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;rIQHws2_lQg&quot;&gt;recent lang team meeting&lt;&#x2F;a&gt; we discussed
the upcoming
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-core&#x2F;0.3.5&#x2F;futures_core&#x2F;stream&#x2F;trait.Stream.html&quot;&gt;&lt;code&gt;Stream&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
RFC. We covered both the steps required to land it, and the steps we&#x27;d want
to take after that. One of the things we&#x27;d want eventually for streams is:
&quot;async iteration syntax&quot;. Just like &lt;code&gt;for x in y&lt;&#x2F;code&gt; works for &lt;code&gt;Iterator&lt;&#x2F;code&gt;, we&#x27;d
want something similar to work for &lt;code&gt;Stream&lt;&#x2F;code&gt;. For example JavaScript support
both
&lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;JavaScript&#x2F;Reference&#x2F;Statements&#x2F;for...of&quot;&gt;sync&lt;&#x2F;a&gt;
and
&lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;JavaScript&#x2F;Reference&#x2F;Statements&#x2F;for-await...of&quot;&gt;async&lt;&#x2F;a&gt;
iteration through &lt;code&gt;for..of&lt;&#x2F;code&gt; loops:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; sync
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;num &lt;&#x2F;span&gt;&lt;span&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; async
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for await &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;event &lt;&#x2F;span&gt;&lt;span&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;emitter&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(event);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However when talking about async iteration syntax in Rust one question has
come up repeatedly:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Should async iteration be parallel or sequential by default?&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;In this post I&#x27;d like to cover the challenges I see with parallel async
iteration, and make the case for, spoilers, defaulting to sequential
iteration semantics.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;However before we continue, the usual disclaimers: &lt;strong&gt;I&#x27;m not on the lang
team. I do not hold any direct decision making power about the Rust language.
I am a member of the Async Foundations WG, but I do not speak for anyone on
the team other than myself.&lt;&#x2F;strong&gt; This post is from my perspective only.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-problem-space&quot;&gt;The problem space&lt;&#x2F;h2&gt;
&lt;p&gt;So the core question we&#x27;re trying to answer is: &quot;should async iteration
default to sequential or parallel?&quot; Putting this into code, it&#x27;s a question
of what some hypothetical future &quot;async iteration&quot; syntax should compile down
to, and which semantics are provided:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; This code...
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; event.await in channel {
&lt;&#x2F;span&gt;&lt;span&gt;    dbg!(event);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ... should it lower into this? (sequential)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(event) = channel.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().await {
&lt;&#x2F;span&gt;&lt;span&gt;    dbg!(event);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ... or should it lower into this? (parallel)
&lt;&#x2F;span&gt;&lt;span&gt;channel.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_par_stream&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;for_each&lt;&#x2F;span&gt;&lt;span&gt;(async |event| dbg!(event));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &quot;lowering&quot; we&#x27;re describing here is not the &lt;em&gt;precise&lt;&#x2F;em&gt; code we&#x27;d expect
the compiler to output. But hopefully it gets the point across. In the
&quot;sequential&quot; case we&#x27;d expect async iteration loops to behave much the same
as async &lt;code&gt;while let Some()&lt;&#x2F;code&gt; loops do today. And in the parallel case, we&#x27;d
expect something to work with semantics similar to those of
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;parallel-stream&#x2F;2.1.1&#x2F;parallel_stream&#x2F;&quot;&gt;parallel-stream&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The main argument I&#x27;ve heard in favor of parallel async iteration semantics
is that in most cases it&#x27;s what people want anyway. For example take the
following code:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::io;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::net::TcpListener;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; listener = TcpListener::bind(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; stream.await? in listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;incoming&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    io::copy(&amp;amp;stream, &amp;amp;stream).await?;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Under sequential iteration semantics this loop would process at most 1 TCP
connection at the time, irregardless of system resources available. But under
parallel iteration semantics, this will have access to all resources
available. The idea is that parallel iteration semantics provide a language
level solution to this problem.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;control-flow-operators&quot;&gt;Control flow operators&lt;&#x2F;h2&gt;
&lt;p&gt;The first issue that arises with parallel async iteration is that the &lt;code&gt;break&lt;&#x2F;code&gt;
and &lt;code&gt;continue&lt;&#x2F;code&gt; control flow operators will have different semantics, or need
to be disallowed altogether. Take the following code:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::io;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::net::TcpListener;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; listener = TcpListener::bind(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Let&amp;#39;s pretend this is valid syntax..
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(i, stream?).await in listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;incoming&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;enumerate&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; i === &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1000 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    io::copy(&amp;amp;stream, &amp;amp;stream).await?;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Say we have a few dozen parallel requests open when we hit &lt;code&gt;break&lt;&#x2F;code&gt;. We should
probably stop accepting new requests. What should happen to the still open
connections?&lt;&#x2F;p&gt;
&lt;p&gt;There is no right answer. We may want to drop them. We may want to keep them
running. More likely the desired behavior may depend on what you&#x27;re doing.
But the semantics will &lt;em&gt;always&lt;&#x2F;em&gt; be different than in regular for loops
&lt;em&gt;because&lt;&#x2F;em&gt; of parallelism.&lt;&#x2F;p&gt;
&lt;p&gt;Adding new semantics to a well-established concept is tricky, and may
actually lead to subtle translation issues when converting existing
algorithms to async Rust. The safest option will be to disallow these
keywords in this context altogether.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;consistency-with-non-async-rust&quot;&gt;Consistency with non-async Rust&lt;&#x2F;h2&gt;
&lt;p&gt;We may want to think of &quot;parallel iteration semantics&quot; as something unique to
async Rust, but in fact non-async Rust faces very similar challenges. To
give a very literal example, the TCP example we used earlier would not be
parallelized in non-async Rust as well:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::io;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::net::TcpListener;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; listener = TcpListener::bind(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; stream in listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;incoming&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; stream = stream?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(reader, writer) = &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;stream, &amp;amp;stream);
&lt;&#x2F;span&gt;&lt;span&gt;    io::copy(reader, writer)?;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Networking in non-async Rust is not the best match, but for example a data
processing pipeline would be. And if we forget to parallelize at the right
points there, we&#x27;ll face very similar issues.&lt;&#x2F;p&gt;
&lt;p&gt;The point being: I don&#x27;t think &quot;parallelism&quot; is a problem unique to async
Rust. And because of that I don&#x27;t think we should look for a solution that&#x27;s
specific to async Rust, but instead look for a solution that can be applied
across domains. I think &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;pull&#x2F;2930&quot;&gt;RFC
2930 (&lt;code&gt;buf_read&lt;&#x2F;code&gt;)&lt;&#x2F;a&gt; is a great example of an
issue that was found in async Rust, but was determined to apply to non-async
Rust as well, and for which a solution was found that can be applied to both
domains.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-would-tasks-be-spawned&quot;&gt;How would tasks be spawned?&lt;&#x2F;h2&gt;
&lt;p&gt;In order for tasks to be parallelized, they would need to be spawned on a
thread pool somehow. Which means a crucial step in enabling parallel
iteration at the language level is to have a notion of an executor as part of
the language.&lt;&#x2F;p&gt;
&lt;p&gt;C++ is &lt;a href=&quot;http:&#x2F;&#x2F;www.open-std.org&#x2F;jtc1&#x2F;sc22&#x2F;wg21&#x2F;docs&#x2F;papers&#x2F;2018&#x2F;p0761r2.pdf&quot;&gt;in the process of
adding&lt;&#x2F;a&gt;
to the language (estimate is C++23), so it&#x27;s not unthinkable for Rust to do
the same. In fact Boats &lt;a href=&quot;https:&#x2F;&#x2F;without.boats&#x2F;blog&#x2F;global-executors&#x2F;&quot;&gt;has written about adding a &lt;code&gt;#[global_executor]&lt;&#x2F;code&gt;
before&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The lowered code from the previous example...
&lt;&#x2F;span&gt;&lt;span&gt;channel.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_par_stream&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;for_each&lt;&#x2F;span&gt;&lt;span&gt;(async |event| dbg!(event));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ... would in turn lower into this
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(event) = channel.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    task::spawn(async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        dbg!(event);
&lt;&#x2F;span&gt;&lt;span&gt;    });
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see we&#x27;re calling &lt;code&gt;task::spawn&lt;&#x2F;code&gt; for each event. That functionality
would need to come from somewhere, and because async iteration is a language
level concern this would mean that functionality would need to become part of
the language.&lt;&#x2F;p&gt;
&lt;p&gt;I think having a way to perform parallel iteration at the language level is a
&lt;em&gt;great&lt;&#x2F;em&gt; idea. And having a &lt;code&gt;#[global_executor]&lt;&#x2F;code&gt; hook with a default
implementation would solve a lot of issues the ecosystem currently has.&lt;&#x2F;p&gt;
&lt;p&gt;But if history is any indicator this would all take quite a while to shake
out. And I think making async iteration syntax depend on this landing (even
if unstable) would mean it might take a lot longer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;parallelizing-send-streams&quot;&gt;Parallelizing !Send streams&lt;&#x2F;h2&gt;
&lt;p&gt;Not all streams are &lt;code&gt;Send&lt;&#x2F;code&gt;, and async iteration should be able to work with
this as well. We can&#x27;t &lt;em&gt;quite&lt;&#x2F;em&gt; propagate &lt;code&gt;!Send&lt;&#x2F;code&gt; the way we do for async
blocks; the global executor would need to support spawning &lt;code&gt;!Send&lt;&#x2F;code&gt; futures as
well. This is not a major hurdle as for example async-stc provides
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.6.3&#x2F;async_std&#x2F;task&#x2F;fn.spawn_local.html&quot;&gt;&lt;code&gt;spawn_local&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
function. But it&#x27;s part of the design space to consider.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;backpressure-concurency-control&quot;&gt;Backpressure &amp;amp; concurency control&lt;&#x2F;h2&gt;
&lt;p&gt;For all its warts something that Node.js streams got right was
&lt;em&gt;backpressure&lt;&#x2F;em&gt;. If for example writing to a file is slower than reading from
a file, the pipeline won&#x27;t keep reading data if the writer isn&#x27;t available.
This ensures your RAM doesn&#x27;t fill up with bytes that are waiting to be written.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;javascript&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-javascript &quot;&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fs &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;require&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;reader &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;createReadStream&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;file.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;compress &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;zlib&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;createGzip&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;writer &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;createWriteStream&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;file.txt.gz&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;reader&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;pipe&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;compress&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;pipe&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;writer&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In Rust sequential async iteration applies backpressure by default. A
translation of the above Node.js code would be somewhat like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; reader = fs::open(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;file.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; writer = fs::open(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;file.txt.gz&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; buf in GzipEncoder::new(reader) {
&lt;&#x2F;span&gt;&lt;span&gt;    writer.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(buf).await?;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-compression&#x2F;0.3.5&#x2F;async_compression&#x2F;stream&#x2F;struct.GzipEncoder.html#impl-Stream&quot;&gt;&lt;code&gt;async-compression&lt;&#x2F;code&gt;&#x27;s &lt;code&gt;Stream&lt;&#x2F;code&gt;
types&lt;&#x2F;a&gt;
already work somewhat like this. Because we&#x27;re performing sequential async
iteration here, reading data from the stream is constrained by the speed at
which we can write. But also vice-versa: the stream is paused if no new data
is available to be read.&lt;&#x2F;p&gt;
&lt;p&gt;If async iteration syntax was parallel by default we would lose backpressure
by default. Which means if no constraints are specified, &lt;strong&gt;by default
parallel async iteration will keep reading data even if there is no consumer
ready to process the data&lt;&#x2F;strong&gt;. Instead limits will always need to be manually
set:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; buf in GzipEncoder::new(reader).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;limit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    writer.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(buf).await?;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There is a third solution to backpressure we haven&#x27;t discussed yet: set
&lt;em&gt;some&lt;&#x2F;em&gt; limit by default. Instead of async iteration having unbounded
parallelism by default, we could say, enable &lt;code&gt;1000&lt;&#x2F;code&gt; items by default. This
limit will however almost always be wrong, and really should be set with
knowledge of the workload.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;name&lt;&#x2F;th&gt;&lt;th&gt;max throughput&lt;&#x2F;th&gt;&lt;th&gt;backpressure?&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;sequential&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;yes&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;bounded&lt;&#x2F;td&gt;&lt;td&gt;n&lt;&#x2F;td&gt;&lt;td&gt;yes&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;unbounded&lt;&#x2F;td&gt;&lt;td&gt;unlimited&lt;&#x2F;td&gt;&lt;td&gt;no&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;how-common-is-parallel-iteration&quot;&gt;How common is parallel iteration?&lt;&#x2F;h2&gt;
&lt;p&gt;A large part of the argument in favor of parallel semantics by default for
async iteration is that it is the most commonly desired semantics. Perhaps
that may be true today within certain domains; but how true do we expect that
to be in the future for across all domains async Rust will cover?&lt;&#x2F;p&gt;
&lt;p&gt;If we want to get a sense of where async Rust might be headed we can take a
look at Node.js streams: they&#x27;ve been around for a decade longer than Rust
streams have. A common kind of stream in the Node.js ecosystem is the
&lt;a href=&quot;https:&#x2F;&#x2F;nodejs.org&#x2F;api&#x2F;stream.html#stream_class_stream_transform&quot;&gt;transform
stream&lt;&#x2F;a&gt;: a
stream that takes an input stream and produces an output stream. Take for
example the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mafintosh&#x2F;csv-parser&quot;&gt;csv-parser package&lt;&#x2F;a&gt;: it
takes a stream of CSV text, and produces an output stream of parsed elements:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;csv&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-csv &quot;&gt;&lt;code class=&quot;language-csv&quot; data-lang=&quot;csv&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;NAME&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;AGE
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Daffy Duck&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;24
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Bugs Bunny&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;22
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;csv &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;require&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;csv-parser&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fs &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;require&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;results &lt;&#x2F;span&gt;&lt;span&gt;= [];
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;createReadStream&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;data.csv&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;)
&lt;&#x2F;span&gt;&lt;span&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;pipe&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;csv&lt;&#x2F;span&gt;&lt;span&gt;())
&lt;&#x2F;span&gt;&lt;span&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;on&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;results&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;on&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;end&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;, () &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;results&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; [
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;   { NAME: &amp;#39;Daffy Duck&amp;#39;, AGE: &amp;#39;24&amp;#39; },
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;   { NAME: &amp;#39;Bugs Bunny&amp;#39;, AGE: &amp;#39;22&amp;#39; }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ]
&lt;&#x2F;span&gt;&lt;span&gt;  });
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Translating this to async Rust (with async iteration syntax) we could have
something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::fs::File;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;csv_parser::Csv;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::io;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; io::Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; file = File::open(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;data.csv&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; item.await? in Csv::new(file) {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;name: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;, age: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, item[&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;NAME&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;], item[&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;AGE&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;]);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this case throughput is likely going to be limited by how fast we can read
from disk, which means spawning tasks for the inner logic is likely not going
to speed this up. In fact, &lt;strong&gt;spawning a task per item may in fact slow down
the parser since the logic of &quot;read the file&quot; and &quot;operate on the file&quot; can
no longer be compiled down into a single state machine&lt;&#x2F;strong&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#inline&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. While
tasks may be cheap compared to threads, they&#x27;re by no means without a cost.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;inline&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Inlining performance really depends on the workload. But as a rule
of thumb: if something can&#x27;t be inlined we&#x27;re likely going to miss out on
optimizations. Obviously &quot;println&quot; isn&#x27;t a good example for something that
can be inlined, but you get the gist.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;The example above could be parallelized, if say, we were processing a
directory of files. We could then spawn a task per file. But each file itself
would still be processed as a sequential stream.&lt;&#x2F;p&gt;
&lt;p&gt;Another example of sequential stream semantics is the HTTP&#x2F;1.1 protocol: the
stream of incoming TCP connections is parallelized, but converting the TCP
stream into a sequence of HTTP requests is sequential. And within the request
itself, each HTTP body is sequential as well. Even a multiplexing protocol
such as HTTP&#x2F;2 eventually breaks down into request &#x2F; response pairs which
have sequential semantics:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; io::Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; parallel
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; stream.await? in TcpListener::accept(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;localhost:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; parallel
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; req.await? in Http2Listener::connect(stream) {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; sequential
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(i, line?).await in req.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;lines&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;                println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;line: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;, value: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, i, line);
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While parallel iteration may be common, it doesn&#x27;t seem likely it will ever
be used in such an overwhelming amount that sequential iteration is made
redundant. It seems most likely people will want to mix both in projects, and
we should seek to make both parallel and async iteration convenient.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;compiler-hints&quot;&gt;Compiler hints&lt;&#x2F;h2&gt;
&lt;p&gt;So far much of this post has been about why &quot;parallel semantics for async
iteration&quot; are not the right default. But this doesn&#x27;t mean that the issue
that intends to address isn&#x27;t worth addressing. Defaulting to parallel
semantics is only one tool.&lt;&#x2F;p&gt;
&lt;p&gt;What if we could use different tools? For example, one issue raised is:
&quot;people might forget to parallelize certain streams, missing out on
performance&quot;. Could we solve this issue through a lint instead? I think we
could, for the most part!&lt;&#x2F;p&gt;
&lt;p&gt;For example clippy could detect known instances of core APIs that are should
probably be parallelized, and warn when they&#x27;re not. For example handling TCP
connections, or processing files in a directory are things you probably want
to do in parallel.&lt;&#x2F;p&gt;
&lt;p&gt;Or if we wanted to allow anyone to add it to their APIs: Rust could introduce
a &lt;code&gt;#[must_par_spawn]&lt;&#x2F;code&gt; hint that could be added to structs, much like &lt;code&gt;#[must_use]&lt;&#x2F;code&gt;.
It could come with a counterpart tag that marks a function as &quot;this spawns
tasks&quot;. And the compiler could warn if something wasn&#x27;t spawned &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#must_not_await&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;must_not_await&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;There is an RFC being written for the
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;wg-async-foundations&#x2F;pull&#x2F;16&quot;&gt;&lt;code&gt;must_not_await&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
hint; going in this direction would not be without precedent.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;must_par_spawn&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;HttpStream;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;par_spawn&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T, F: Future&amp;lt;Output = T&amp;gt; + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;: F) -&amp;gt; T;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Both solutions would need work before implementing; but they present
alternate directions that can be explored instead of resorting to parallel
async iteration syntax.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tool-assisted-optimization&quot;&gt;tool-assisted optimization&lt;&#x2F;h2&gt;
&lt;p&gt;In the post &lt;a href=&quot;https:&#x2F;&#x2F;without.boats&#x2F;blog&#x2F;futures-and-segmented-stacks&#x2F;&quot;&gt;Futures and Segmented
Stacks&lt;&#x2F;a&gt; Boats talks
about techniques to make futures more efficient by moving their stack onto
the heap. Locating where to segment your stack is hard to do by hand, but
could likely become trivial with the right tooling.&lt;&#x2F;p&gt;
&lt;p&gt;Parallelism has many similarities: finding the right places to parallelize
can be tricky. Having a tool that can locate where tasks should be spawned,
and which tasks aren&#x27;t needed would be great. Runtime profiling for async
programs seems like a generally underexplored domain, and I suspect more and
better tooling could get us really far.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;parallel-iteration-syntax&quot;&gt;Parallel iteration syntax&lt;&#x2F;h2&gt;
&lt;p&gt;So far in this post we&#x27;ve talked about why async iteration shouldn&#x27;t default
to parallel semantics by &lt;em&gt;default&lt;&#x2F;em&gt;. But I do agree that it would be great if
we had &lt;em&gt;some&lt;&#x2F;em&gt; syntax for parallel iteration. In the &quot;future directions&quot;
section of my
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;parallel-stream&#x2F;#future-directions&quot;&gt;parallel-stream&lt;&#x2F;a&gt;
post, I laid out what that could look like (using &lt;code&gt;par for&lt;&#x2F;code&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; listener = TcpListener::bind(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;span&gt;par &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; stream.await? in listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;incoming&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    io::copy(&amp;amp;stream, &amp;amp;stream).await?;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In &lt;code&gt;par for&lt;&#x2F;code&gt; loops keywords such as &lt;code&gt;break&lt;&#x2F;code&gt; and &lt;code&gt;continue&lt;&#x2F;code&gt; would be invalid,
and each task would be spawned on a task. This syntax could be made to work
for both sync and non-async Rust, backed by different execution strategies.
And finally, being able to talk about parallelism as a first-class language
concept would enable much better diagnostics, documentation, and tooling to
be implemented.&lt;&#x2F;p&gt;
&lt;p&gt;For example, accidentally writing &lt;code&gt;for x.await&lt;&#x2F;code&gt; instead of &lt;code&gt;par for x.await&lt;&#x2F;code&gt;
on a struct tagged as &lt;code&gt;#[must_par_spawn]&lt;&#x2F;code&gt; could be met with the following
diagnostic:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;warning: loop is sequential
&lt;&#x2F;span&gt;&lt;span&gt; --&amp;gt; src&#x2F;main.rs:2:9
&lt;&#x2F;span&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;span&gt;2 |     for stream.await? in listener.incoming() {
&lt;&#x2F;span&gt;&lt;span&gt;  |     ^ help: use `par for stream.await? in listener.incoming()` to parallelize
&lt;&#x2F;span&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;span&gt;  = note: `#[warn(sequential_loops)]` on by default
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I think parallel iteration syntax in some form would be &lt;em&gt;fantastic&lt;&#x2F;em&gt;. I just
would like to see it exist in a similar way for both async and non-async
Rust.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;addendum-lending-streams&quot;&gt;Addendum: lending streams&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;scottmcm&quot;&gt;Scottmcm&lt;&#x2F;a&gt; pointed out on Zulip that parallel
iteration semantics also wouldn&#x27;t work well with
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;wg-async-foundations&#x2F;blob&#x2F;6dd2c54cb1523b1a97178df264ba7396c6e53f1b&#x2F;rfc-drafts&#x2F;stream.md#lending-streams&quot;&gt;lending streams&lt;&#x2F;a&gt;
(also known as &quot;streaming&quot; or &quot;attached&quot; streams).&lt;&#x2F;p&gt;
&lt;p&gt;In a lending stream the &lt;code&gt;Item&lt;&#x2F;code&gt; that gets returned by &lt;code&gt;Stream&lt;&#x2F;code&gt; may be borrowed
from self. It can only be used as long as the self reference remains live.
For example a &lt;code&gt;Stream&lt;&#x2F;code&gt; where:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;iter&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; = &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;iter mut&lt;&#x2F;span&gt;&lt;span&gt; State;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;...would fail to compile, which seems rather limiting.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Parallel iteration semantics for &lt;code&gt;Stream&lt;&#x2F;code&gt; are an incredible concept that has
with much potential, but it seems unlikely to be the right fit for all cases.&lt;&#x2F;p&gt;
&lt;p&gt;By defaulting to sequential iteration semantics for &lt;code&gt;Stream&lt;&#x2F;code&gt; parity with
&lt;code&gt;Iterator&lt;&#x2F;code&gt; is preserved. This not only ensures keywords such as &lt;code&gt;break&lt;&#x2F;code&gt; and
&lt;code&gt;continue&lt;&#x2F;code&gt; work in a comparable way, it also enables looking at the design of
&quot;parallel iteration&quot; as a design that can be shared between async and
non-async Rust.&lt;&#x2F;p&gt;
&lt;p&gt;We still have a fair bit to go before we can add async iteration syntax to
Rust. The &lt;code&gt;Stream&lt;&#x2F;code&gt; RFC draft still needs to be submitted and accepted. There
are still questions about migrations and interop with the stream adapters in
the ecosystem. And a design that covers everything from &lt;code&gt;IntoStream&lt;&#x2F;code&gt; to
syntax &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#syntax&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. But even though all that may still be a while; hopefully
this post can serve to anchor discussion on whether iterating over a &lt;code&gt;Stream&lt;&#x2F;code&gt;
should default to sequential or parallel &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#pants&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;syntax&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;All async iteration syntax in this post has been made up, and is
by no means an indication of what the lang team will decide on. I just needed
something up for the purpose of this post.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;pants&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;I really tried making a joke about &quot;If a stream would wear
iteration, would it wear it this way, or that way&quot; but couldn&#x27;t get it to
work. My biggest regret in publishing this post.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;Thanks to Friedel Ziegelmayer and Florian Gilcher for proof reading.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Notebooks</title>
            <pubDate>Mon, 27 Jul 2020 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/notebooks/</link>
            <guid>https://blog.yoshuawuyts.com/notebooks/</guid>
            <description>&lt;p&gt;Ever since I picked up programming in 2013 I haven&#x27;t really stopped.
Weekdays, weekends, evenings. I&#x27;ve spent much of my adult life obsessing
about programs. But that&#x27;s come at a cost: over the years I&#x27;ve started to
realize what I&#x27;ve been trading for the time spent working on projects. And I
realized I needed to change course.&lt;&#x2F;p&gt;
&lt;p&gt;Desiring change is a useful starting point; but it needs to be followed up by
execution. My default mode of doing things was: &quot;drop everything, focus on
the new thing&quot;, but that was the root of the problem I was trying to address
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#saisho&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. I realized this wasn&#x27;t enough, and what I needed was the ability
to formulate plans and the ability to review.&lt;&#x2F;p&gt;
&lt;p&gt;The answer for me has been to adopt a framework: a notebook, pen, and ruler.
In this post I want to share more on how that&#x27;s worked for me.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;saisho&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;I &lt;a href=&quot;https:&#x2F;&#x2F;saisho.yoshuawuyts.com&#x2F;&quot;&gt;made a list of things I wanted to
do&lt;&#x2F;a&gt; in Jan 2018. That year I only managed to
do the first thing on the list. &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yoshuawuyts?tab=overview&amp;amp;from=2018-01-01&amp;amp;to=2018-12-31&quot;&gt;My 2018 GitHub
contribs&lt;&#x2F;a&gt;
are a testament to the absurd amount of time spent. Looking back at this list
two years later was confrontational and made me realize that I needed to
actively change my approach if I ever wanted to make progress on the things I
cared about.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;bullet-journal-a-paper-os&quot;&gt;bullet journal: a paper OS&lt;&#x2F;h2&gt;
&lt;p&gt;In January I first learned about &quot;bullet journalling&quot; through the &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=ZK5VUuxGYr0&quot;&gt;Pick Up
Limes channel on YouTube&lt;&#x2F;a&gt;. The
whole video is worth a watch, but this passage really stood out to me:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I genuinely didn&#x27;t know how I functioned before this system. Because I was
someone who had notes everywhere. [...] It always felt like there was
information coming at me from every direction, but at the same time I
couldn&#x27;t really find anything when I was looking for it. But now, with this
system, I feel like I&#x27;ve got a little built-in secretary always reminding me
of what I need to do.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Someone was telling me that &lt;em&gt;a notebook&lt;&#x2F;em&gt; could act as a secratary? That
sounded amazing, and I wanted to learn more! &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#paper&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; So I read the book
&lt;em&gt;&quot;The Bullet Journal Method&quot;&lt;&#x2F;em&gt;. In it the author Ryder Carroll lays out a
framework for taking notes he describes as an &quot;OS for managing your life&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;The core tennets of the system are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A system to quickly take notes and categorize them (&quot;rapid logging&quot;).&lt;&#x2F;li&gt;
&lt;li&gt;A time structure to organize lists by (daily, monthly, yearly).&lt;&#x2F;li&gt;
&lt;li&gt;Key moments when and how to interact with the journal.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A key reason why this has to be on paper is that the expression of these
ideas is inherently personalized. Every person has different requirements for
what they need to track, and a physical notebook is about the only medium
that can provide this degree of flexibility. It&#x27;s a system that serves the
needs you have here and now, and adapts to your needs over time.&lt;&#x2F;p&gt;
&lt;p&gt;Another quality of paper is that every action on it takes effort. You cannot
automate a notebook; the most convenient you can make it is to create a
framework. This ensures you have an active relationship with your notes.
Nothing will automatically be added. Nothing will automatically be carried
over. Every entry is deliberate. And this provides opportunity to reflect and
prioritize.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;paper&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Admittedly I had to overcome a kneejerk reaction to dismiss paper
as the right interface to take notes. I suspect this may be due to some
ingrained tech exceptionalism, but I went into it thinking: &quot;How can I turn
this into an app later?&quot; The answer is: it wouldn&#x27;t work well. Paper is
infinitely versatile and allows adapting layouts to be best suited for you,
at a given time. It&#x27;s an interface that evolves with you. And no app can
replace that.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;tools&quot;&gt;Tools&lt;&#x2F;h2&gt;
&lt;p&gt;It&#x27;s possible to bullet journal as long as you have a notebook and pen. But
these are the tools I use:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Notebook: &lt;a href=&quot;https:&#x2F;&#x2F;www.leuchtturm1917.de&#x2F;notizbuch-medium-a5-hardcover-251-nummerierte-seiten.html&quot;&gt;LEUCHTTURM1917 A5 hardcover dotted&lt;&#x2F;a&gt; — 18 EUR&lt;&#x2F;li&gt;
&lt;li&gt;Pen: &lt;a href=&quot;https:&#x2F;&#x2F;www.stabilo.com&#x2F;com&#x2F;products&#x2F;writing&#x2F;fineliner-felt-tip-pens&#x2F;stabilo-point-88&#x2F;&quot;&gt;Stabilo point 88, fine 0.4mm&lt;&#x2F;a&gt; — 2 EUR&lt;&#x2F;li&gt;
&lt;li&gt;Ruler: &lt;a href=&quot;https:&#x2F;&#x2F;www.modulor.de&#x2F;en&#x2F;rumold-ruler-plastic.html&quot;&gt;Rumold transparent&lt;&#x2F;a&gt; — 1 EUR&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I estimate I go through about 3 notebooks per year, estimating my equipment
cost to be about 6 euros per month. I also highly recommend using a
transparent ruler if you can find one, as I found it easier to use than
opaque variants.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;journaling-in-practice&quot;&gt;Journaling in practice&lt;&#x2F;h2&gt;
&lt;p&gt;Did I say journals are customized to the owner&#x27;s needs? There is no &lt;em&gt;right&lt;&#x2F;em&gt;
way to journal; but here&#x27;s how I do it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-blank-spread&quot;&gt;The blank spread&lt;&#x2F;h2&gt;
&lt;img src=&quot;&#x2F;assets&#x2F;notebooks&#x2F;blank.png&quot; alt=&quot;blank spread&quot; style=&quot;max-width:600px;width:100%&quot;&gt;
&lt;p&gt;Each page in the journal is empty when you start out. I was so daunted by it
the first time I started: I was afraid of making mistakes and doing things
wrong. A blank page has no system yet; no relationship to any other page
either. And that&#x27;s okay. We get to define that, and the most important part
is to start.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;daily-log&quot;&gt;Daily log&lt;&#x2F;h2&gt;
&lt;img src=&quot;&#x2F;assets&#x2F;notebooks&#x2F;weekly.png&quot; alt=&quot;daily spread&quot; style=&quot;max-width:600px;width:100%&quot;&gt;
&lt;p&gt;Every Sunday I plan my week ahead. I create a new daily log spread, and I
copy over all dates and tasks for the week over from my monthly log. And I
copy over the tasks from the week before that I need to do this week. This
means when Monday rolls around I don&#x27;t start at a deficit, but instead
already know what I need to work on.&lt;&#x2F;p&gt;
&lt;p&gt;My daily journal is a two-page spread that starts on Monday and ends on
Sunday. This leaves 1&#x2F;8th of the pages over to write notes, which I usually
use to note extra tasks for the week, or tasks to carry over to the next
week.&lt;&#x2F;p&gt;
&lt;p&gt;I start each day with a list of things I need to do (including meetings and
things to read). And end the day with a list of things I have done. If I&#x27;ve
missed something I carry it over to another day, or file it in my monthly
log.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;monthly-log&quot;&gt;Monthly log&lt;&#x2F;h2&gt;
&lt;img src=&quot;&#x2F;assets&#x2F;notebooks&#x2F;monthly.png&quot; alt=&quot;monthly spread&quot; style=&quot;max-width:600px;width:100%&quot;&gt;
&lt;p&gt;The monthly log provides a wider breakdown of the month. These are the 14
pages after the yearly log. That is 6 months + 2 pages to capture events
after that. The idea is that we&#x27;ll run out of notebook pages before we reach
the end of the 6-month period.&lt;&#x2F;p&gt;
&lt;p&gt;On the left hand of each page there&#x27;s a line per day, with little markings to
delimate each week. And on the right side there&#x27;s space for todos for the
month. I like to plan this spread out at the start of the month. I filter and
carry over uncompleted tasks from the prior month. And copy over entries from
the yearly log.&lt;&#x2F;p&gt;
&lt;p&gt;The monthly log is also a good place for habit tracking. On the right side of
the left page I have a column marked &quot;e&quot; (for &quot;exercise&quot;) that I add a small
x on the day of whenever I&#x27;ve done exercise. This allows me to see at a
glance how I&#x27;ve been doing (17 entries so far this month).&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve recently started experimenting with task prioritization on the right
page. On the bottom half of the page I create two columns: one with things
(projects?) I&#x27;m currently working on. And one with goals (projects?) I would
like to be doing. Assuming I need to drop something in order to make time for
something new, I can then figure out how to break it down further.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;yearly-log&quot;&gt;Yearly log&lt;&#x2F;h2&gt;
&lt;img src=&quot;&#x2F;assets&#x2F;notebooks&#x2F;yearly.png&quot; alt=&quot;yearly spread&quot; style=&quot;max-width:600px;width:100%&quot;&gt;
&lt;p&gt;The first 4 pages in any notebook make up the yearly log. This is an overview
of each month; with 3 months per page. Here I write down important events,
anniversaries, birthdays, and major upcoming events. I fill this out whenver
I get a new notebook, filtering and carrying over the yearly log from an
earlier notebook. It also serves to plan year-scale events such as holidays
on.&lt;&#x2F;p&gt;
&lt;p&gt;When first starting a notebook this is a fun section to start with. Look up
national holidays. Ask friends when their birthdays are. Schedule and spread
out vacations. Look up conference days, book releases, movie releases.&lt;&#x2F;p&gt;
&lt;p&gt;I usually only consult the yearly log at the start of the month to carry over
events to the monthly log, and whenever I find out about a friend&#x27;s birthday
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#birthdays&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. But hopefully I&#x27;ll find some other uses for the yearly log in
the future — this is a useful timescale to look at things through, and one I
don&#x27;t nearly do enough.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;birthdays&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;For any pal reading this who&#x27;s casually mentioned their
birthday. I&#x27;ve been keeping track, hehe.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;custom-daily-exercise-log&quot;&gt;Custom: Daily exercise log&lt;&#x2F;h2&gt;
&lt;img src=&quot;&#x2F;assets&#x2F;notebooks&#x2F;exercise.png&quot; alt=&quot;exercise spread&quot; style=&quot;max-width:600px;width:100%&quot;&gt;
&lt;p&gt;The spreads I&#x27;ve covered so far are fairly standard. They&#x27;re almost 1:1
implementations of Ryder Carroll&#x27;s base templates. I like them because
they&#x27;re easy to create and take minimal upkeep.&lt;&#x2F;p&gt;
&lt;p&gt;But one project that didn&#x27;t quite fit in that mold was tracking and planning
exercise. Or well; the way I solve it was by creating another weekly log that
I use to plan and track exercise in.&lt;&#x2F;p&gt;
&lt;img src=&quot;&#x2F;assets&#x2F;notebooks&#x2F;exercises_list.png&quot; alt=&quot;exercise list spread&quot; style=&quot;max-width:600px;width:100%&quot;&gt;
&lt;p&gt;At the front of my notebook I reserve two pages for for exercises. The left
page contains a collection of sets I can do. And the right page individual
exercises catagorized per muscle group. This much resembles the
meals&#x2F;groceries spread, but for exercise.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;custom-daily-meals-groceries&quot;&gt;Custom: daily meals&#x2F;groceries&lt;&#x2F;h2&gt;
&lt;img src=&quot;&#x2F;assets&#x2F;notebooks&#x2F;meals_groceries.png&quot; alt=&quot;meals and groceries spread&quot; style=&quot;max-width:600px;width:100%&quot;&gt;
&lt;p&gt;I realized last year that my partner and I were ordering in food several
times a week. The reason for that was because we couldn&#x27;t find the time to
cook, even for fun on the weekends. So I wanted to find a way to lower the
barrier.&lt;&#x2F;p&gt;
&lt;p&gt;The answer ended up being a combination of several things: decide what to
cook ahead of time, make sure we&#x27;re stocked, and keep a clean cooking surface
at all times. This is still a work in progress, but being able to plan meals
and groceries is a useful tool to have.&lt;&#x2F;p&gt;
&lt;p&gt;The way we do this is by creating a spread with on the left-hand side an
overview of meals for the week: per-day breakdown at the top, and individual
recipes at the bottom. And an overview of ingredients on the right-hand side.&lt;&#x2F;p&gt;
&lt;p&gt;On a good week I sit down with my partner and talk about what we want to cook
that week. Then I do a full index of what we need to prepare those meals
with. I then cross out what we already have in the house from the list. And
finally take a look at the list of staples in the front of the notebook and
check whether we&#x27;re missing any. We then end up with a decent list of things
we need to buy for the week, and are ready to do a grocery run.&lt;&#x2F;p&gt;
&lt;p&gt;Sometimes we still unexpectedly make plans with pals, or have meetings run
over that prevent cooking meals. But if planned well you roll over meals, or
postpone them for the week after. This takes some practice though.&lt;&#x2F;p&gt;
&lt;img src=&quot;&#x2F;assets&#x2F;notebooks&#x2F;grocery_list.png&quot; alt=&quot;groceries index spread&quot; style=&quot;max-width:600px;width:100%&quot;&gt;
&lt;p&gt;Figuring out what to buy from the store can be a tedious process. So I like
to keep a list of staples in the front of the notebook (somewhere after the
monthly logs, before the first daily log). It&#x27;s a useful reference that
allows me to quickly check whether I&#x27;m missing something, or I can check it
for inspiration on what to cook.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;custom-sleep-log&quot;&gt;Custom: sleep log&lt;&#x2F;h2&gt;
&lt;img src=&quot;&#x2F;assets&#x2F;notebooks&#x2F;sleep.jpg&quot; alt=&quot;sleep page&quot; style=&quot;max-width:600px;width:100%&quot;&gt;
&lt;p&gt;One thing I started tracking earlier this year was my sleeping patterns. I
noticed I had trouble falling asleep, trouble waking up, and felt pretty sad
a lot of the time. I figured this would be helpful to track. I no longer
track it (yay good sleep!), but the image above is my sleep for the month
February. &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#feb&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;feb&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;Probably the worst day that month was when I hit 4 and then 5 hours
of sleep, then went for dinner with friends, and had to organize 20 people to
get to a bar. I also caught wind the contract I was negotiating unexpectedly
fell through. The whole week was pretty rough. But it probably would&#x27;ve been
worse if I hadn&#x27;t been aware of my sleeping patterns.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;social&quot;&gt;Social&lt;&#x2F;h2&gt;
&lt;p&gt;Something new I&#x27;ve started, and am still working on, is keeping track of
interactions with friends and acquiantances. There are people who I used to
interact with regularly but for whatever reason don&#x27;t interact with enough.
And other people who I wish I was closer with, but am not.&lt;&#x2F;p&gt;
&lt;p&gt;This requires active planning, tracking, and considering. I know how nice it
is when a friend I haven&#x27;t heard of in a while reaches out — it doesn&#x27;t have
to be much really. I want to be that person for others. The friend who gets
in touch; who reaches out.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m still experimenting with the right system for this, and reading up on
material how to be better (I just started &lt;a href=&quot;https:&#x2F;&#x2F;weshouldgettogether.com&#x2F;&quot;&gt;&quot;we should get
together&quot;&lt;&#x2F;a&gt;). Perhaps I&#x27;ll figure something
out here and have something to share in the future.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tidying&quot;&gt;Tidying&lt;&#x2F;h2&gt;
&lt;p&gt;Something I&#x27;ve desired to do for a few years has been to be better around the
house. Clean more often, do more chores. Part of this has been communication
with my partner. Part doing research on how to actually keep a house tidy
(konmari actually worked for me). And much of it I&#x27;ve been able to track
through my notebook.&lt;&#x2F;p&gt;
&lt;p&gt;I now clean the windows once every 3 months. I&#x27;ve created a daily habit of
cleaning up in the mornings. I keep a list of chores to do when I have time
available. This has gradually helped me get better around the house, which is
not only nice for the people I live with. It makes me feel more calm and in
touch with where I spend most of my time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;events&quot;&gt;Events&lt;&#x2F;h2&gt;
&lt;p&gt;In the two months before the pandemic my partner and I started going to shows
more. Every month I&#x27;d look up events around Berlin, and we&#x27;d plan them in to
go see throughout the month.&lt;&#x2F;p&gt;
&lt;p&gt;Because it&#x27;s so easy to go through the same loop every day. Days turn into
weeks. Weeks into months. And in my case: it feels like little has changed
for me in the last 3 years. Making an active effort to do new things is
something I wanted to do.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately the pandemic has thrown a bit of a wrench into this, but I
still wanted to share this actually worked really well for as long as I did
it. With lockdown measures decreasing in Berlin I probably should cautiously
try something like this again: even if it&#x27;s just parks to visit, areas to go,
or recipes to try.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;This has been an overview of how I use my notebook to track much of my life.
I started doing this 8 months ago, and I feel it&#x27;s helped me gain more
control of my life. Perhaps you&#x27;ll find this useful too.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;further-resources&quot;&gt;Further Resources&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=fm15cmYU0IM&quot;&gt;Bullet Journal on YouTube&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;bulletjournal.com&#x2F;pages&#x2F;book&quot;&gt;The Bullet Journal Method book&lt;&#x2F;a&gt; (The audiobook is ~4 hours)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
        </item>
        <item>
            <title>Reliability</title>
            <pubDate>Sat, 02 May 2020 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/reliability/</link>
            <guid>https://blog.yoshuawuyts.com/reliability/</guid>
            <description>&lt;p&gt;Last December I turned 28, and last September marked 6 years since I started
programming&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#time&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Reflecting on the past I&#x27;m quite pleased with what I&#x27;ve
achieved. But every now and then I like to take a moment to look ahead and
think about what I want to work on next. This is a post sharing some thoughts.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;time&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Time is a weird one. Last March felt like it lasted a quarter. April
felt like it lasted at most two weeks. I don&#x27;t know how many years I&#x27;ll have
in this industry, but it seems likely I&#x27;ll have more time remaining working
in it than that I&#x27;ve spent so far. So it&#x27;s worth planning ahead and
considering what to invest in that will pay off in the long run.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;which-things-are-hard-for-me&quot;&gt;Which things are hard for me?&lt;&#x2F;h2&gt;
&lt;p&gt;There are an infinite number of things in the realm of computers that I&#x27;m not
good at. Some include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Designing algorithms. I never put in the hours, so I&#x27;m just not good at it.&lt;&#x2F;li&gt;
&lt;li&gt;Writing reliable software in one go. My work tends to need several bug-fixing cycles.&lt;&#x2F;li&gt;
&lt;li&gt;Atomics and lock-free algorithms. This is like algorithms, but harder.&lt;&#x2F;li&gt;
&lt;li&gt;Everything graphics and hardware. I haven&#x27;t spent any time in either field.&lt;&#x2F;li&gt;
&lt;li&gt;Optimizing performance. I&#x27;m not good at measuring performance, let alone
improving it.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Some things that I used to think were hard, but have gotten better at are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;In 2018 a goal I set for myself was to become fluent in Rust.&lt;&#x2F;li&gt;
&lt;li&gt;In 2019 I wanted to become fluent in async Rust and make it more accessible.&lt;&#x2F;li&gt;
&lt;li&gt;In 2019 I wanted to both gain confidence and skill at writing.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This year I&#x27;d like to continue my work on Async Rust, with a continued focus
on the web space. This is a critical area for Rust to succeed in, as success
in that field means more people will be able to use Rust at their jobs, which
in turn means we can expect larger investments to go into Rust. But to me
that seems mostly like a matter of putting in the hours now. A personal goal
for professional growth I&#x27;d like to set is to become better at authoring
&lt;em&gt;reliable software&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;reliability&quot;&gt;Reliability&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&quot;It&#x27;s been amazing working with &amp;lt;colleague&amp;gt;. They managed to implement &amp;lt;feature&amp;gt;
in record time, and it&#x27;s since worked flawlessly. I&#x27;ve never seen
anything like it.&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;— A colleague describing another colleague&#x27;s work last year, paraphrased.&lt;&#x2F;p&gt;
&lt;p&gt;This exchange has really stuck with me -- because I realized that it didn&#x27;t
just describe &lt;em&gt;some&lt;&#x2F;em&gt; of my colleague&#x27;s work. It described &lt;em&gt;all&lt;&#x2F;em&gt; of their work.
It felt like their work consistently had fewer bugs than everyone else,
while often also being friendly to use and rich in features. Even when
building complex and novel programs.&lt;&#x2F;p&gt;
&lt;p&gt;I aspire for my work to be of the same quality. I feel I&#x27;m able to produce
designs that are friendly to use, fairly quickly. But it&#x27;s nowhere near the
level of reliability that I would want it to be. Which means I spend a fair
amount of time fixing bugs after publication. And I&#x27;d like to do better!&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s why I&#x27;d like to make it an explicit goal for myself over the next year
to improve the &lt;em&gt;reliability&lt;&#x2F;em&gt; of my work. It&#x27;ll be a fun challenge to
bring down the number of bugs in my work in a structured way.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;approach&quot;&gt;Approach&lt;&#x2F;h2&gt;
&lt;p&gt;My initial thesis is that &quot;reliable software&quot; is made up of three parts that
can be individually improved:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The software that provides the functionality we actually want.&lt;&#x2F;li&gt;
&lt;li&gt;Assertions to validate the software works as intended.&lt;&#x2F;li&gt;
&lt;li&gt;Introspection tools to help debug problems.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Even slight progress on these facets will have a compounding effect on the
reliability of my work.&lt;&#x2F;p&gt;
&lt;p&gt;My starting point for &quot;better software&quot; is the talk &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;3AxSwCC7I4s&quot;&gt;&quot;PID Loops and the Art
of Keeping Systems Stable&quot; by Colm
MacCárthaigh&lt;&#x2F;a&gt;. The talk is about bringing
practices from industrial control systems to everyday software engineering.
It covers many useful concepts that seem worth trying out; in particular the
notion of building &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;3AxSwCC7I4s?t=1257&quot;&gt;&quot;measure-first&quot;&lt;&#x2F;a&gt;
software seems intriguing. It also seems &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;state-machines&#x2F;&quot;&gt;state
machines&lt;&#x2F;a&gt; could play a part
here.&lt;&#x2F;p&gt;
&lt;p&gt;My starting point for &quot;better tests&quot; is fuzzing and property testing &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#fuzz&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. For the
&lt;a href=&quot;https:&#x2F;&#x2F;datrs.yoshuawuyts.com&#x2F;&quot;&gt;datrs&lt;&#x2F;a&gt; project I wrote property tests for
most modules, which helped catch many bugs &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#talk&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. &lt;code&gt;cargo-fuzz&lt;&#x2F;code&gt; now has
support for &lt;a href=&quot;https:&#x2F;&#x2F;rust-fuzz.github.io&#x2F;book&#x2F;cargo-fuzz&#x2F;structure-aware-fuzzing.html&quot;&gt;structure-aware
fuzzing&lt;&#x2F;a&gt;,
and I recently became aware Fred Hebert (of Erlang fame) wrote a &lt;a href=&quot;https:&#x2F;&#x2F;pragprog.com&#x2F;book&#x2F;fhproper&#x2F;property-based-testing-with-proper-erlang-and-elixir&quot;&gt;proptest
book&lt;&#x2F;a&gt;.
Making fuzz testing a regular part of my workflow will likely yield large returns.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;fuzz&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Fuzz &#x2F; property testing in a nutshell: write a program that can
generate test cases enabling software to be much more thoroughly tested.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;talk&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;I gave a talk about it &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;EPgtvKMF7VQ&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;My starting point for &quot;better introspection&quot; is to really up the amount and
quality of logs I write. I often don&#x27;t add logs to my work until the very
end, and even then it leaves much to be desired. Being much more proactive
with this will make systems much easier to debug, which in turn means less
time spent debugging. &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;mycoliza&#x2F;status&#x2F;1256008354767310848&quot;&gt;The work Eliza shared
yesterday&lt;&#x2F;a&gt; provides
a glimpse of what better introspection tools can be like, and has me excited
about possibilities here.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post I&#x27;ve covered why software reliability matters, and how I plan to
improve:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Adopt patterns to write inherently more reliable software.&lt;&#x2F;li&gt;
&lt;li&gt;Use automation to test more often, and more thoroughly.&lt;&#x2F;li&gt;
&lt;li&gt;Make writing log points a regular part of my workflow.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;I&#x27;m sure as time goes on I&#x27;ll learn about more approaches, and deepen my
understanding of what makes reliable software. Some of these ideas might not
work as expected, or take too much time to be practical. But I want to
actively try and build more reliable software, and as always I&#x27;ll be
documenting the process.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Fallible Iterator Adapters</title>
            <pubDate>Sun, 12 Apr 2020 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/fallible-iterator-adapters/</link>
            <guid>https://blog.yoshuawuyts.com/fallible-iterator-adapters/</guid>
            <description>&lt;p&gt;A great aspect of the Rust stdlib is that many common operations are provided
with a shared idiom. Rather than say having to remember how to write a
correct sort function by hand, the stdlib provides a fast one for you.&lt;&#x2F;p&gt;
&lt;p&gt;One of the places with the most such conveniences is the
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.Iterator.html&quot;&gt;&lt;code&gt;std::iter::Iterator&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
trait. This trait provides a rich set of operations for filtering, combining
and merging streams of items. And because iterators are lazy they&#x27;re
incredibly efficient too &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#lazy&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;lazy&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Work doesn&#x27;t start until a driver method calls it. Examples include
&lt;code&gt;next&lt;&#x2F;code&gt;, &lt;code&gt;fold&lt;&#x2F;code&gt;, and &lt;code&gt;for_each&lt;&#x2F;code&gt;. Also because of the way Rust&#x27;s iterators are
setup the compiler can inline them until only the smallest possible state
machine remains. Not all languages can do this, and the result is really cool!&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;However one downside to iterators is that they don&#x27;t play well with all
input. In particular there are some limits around &lt;code&gt;Result&lt;&#x2F;code&gt; (and &lt;code&gt;Try&lt;&#x2F;code&gt; in
general). When using any stream adapter with fallible input&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#monads&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, we generally
want to be able to do several things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;We want to stop iterating (short-circuit) when we encounter an error.&lt;&#x2F;li&gt;
&lt;li&gt;We want to be able to return the error out of the iterator so it can be
bubbled up.&lt;&#x2F;li&gt;
&lt;li&gt;We never want to have to ignore errors.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;monads&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Someone who understands monads better would probably be able to
state this more eloquently. But I&#x27;m not a language designer, so hopefully I
can get away with waving my hands a bit here.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;For example with the &lt;code&gt;try_for_each&lt;&#x2F;code&gt; function we&#x27;re able to take a vec of
names, and perform some IO operation on them. This will stop iterating over
file names if an error occurs, and will immediately return the error:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::io::{stdout, Write};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; data = [&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;no_tea.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;stale_bread.json&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;torrential_rain.png&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;];
&lt;&#x2F;span&gt;&lt;span&gt;data.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_for_each&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;| {
&lt;&#x2F;span&gt;&lt;span&gt;    writeln!(stdout(), &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, x)?;
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;})?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This works pretty smoothly. Now imagine we wanted to do something with IO
operations. Say we had a folder for a database, and we wanted to compare the
content of several files with each other, finding the smallest string by
index &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#example&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;example&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Yes I know this example is completely unreasonable, but it&#x27;s late
here and I had to come up with something that did some IO. &lt;code&gt;min_by&lt;&#x2F;code&gt; is the
actual method a friend brough up when building a database though, so at least
we&#x27;re hitting the right method here (:&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Now we would likely want to use something like &lt;code&gt;fs::read&lt;&#x2F;code&gt; and
&lt;code&gt;Iterator::min_by&lt;&#x2F;code&gt;, which we could do as such:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; offsets = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;9&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;18&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;22&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;17&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = db_files.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;min_by&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;y&lt;&#x2F;span&gt;&lt;span&gt;| {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; fx = fs::read_file(format!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;.db&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;.index&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;), x).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; fy = fs::read_file(format!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;.db&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;.index&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;), y).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    fx.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;cmp&lt;&#x2F;span&gt;&lt;span&gt;(fy)
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now as you might have noticed, we need to use &lt;code&gt;unwrap&lt;&#x2F;code&gt; here. Oh no! What this
practically means is that if any error occurs when reading files our program
will panic. Which means that &lt;code&gt;Iterator::min_by&lt;&#x2F;code&gt; probably shouldn&#x27;t be used
here, and we should turn this into manual loop logic instead.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;surveying-fallible-adapters&quot;&gt;Surveying Fallible Adapters&lt;&#x2F;h2&gt;
&lt;p&gt;In order to figure out which methods are incompatible with fallible
operations we should take a look at &lt;em&gt;all&lt;&#x2F;em&gt; methods on &lt;code&gt;Iterator&lt;&#x2F;code&gt;. The only
methods that have the potential to be incompatible are the ones that take
closures.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ve created an overview of all iterator methods that take closures. Here we
look at the iterator adapter name, the signature of the closure that&#x27;s
passed, and whether it can short-circuit on error. Finally we also look at
whether it has a fallible counterpart that &lt;em&gt;can&lt;&#x2F;em&gt; short-circuit.&lt;&#x2F;p&gt;
&lt;p&gt;In the following overview there are probably ways to make certain methods
work with errors, or perhaps they work if &lt;code&gt;Result&lt;&#x2F;code&gt; has been passed into the
method, but does not originate &lt;em&gt;from&lt;&#x2F;em&gt; the method. The measure we&#x27;ll be using
is whether the &lt;code&gt;?&lt;&#x2F;code&gt; operator can be used inside the closure.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Name&lt;&#x2F;th&gt;&lt;th&gt;Closure Signature&lt;&#x2F;th&gt;&lt;th&gt;Accepts try operator?&lt;&#x2F;th&gt;&lt;th&gt;Fallible counterpart&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;all&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(Self::Item) -&amp;gt; bool&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;any&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(Self::Item) -&amp;gt; bool&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;cmp_by&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(Self::Item, &amp;lt;I as IntoIterator&amp;gt;::Item) -&amp;gt; Ordering&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;eq_by&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(Self::Item, &amp;lt;I as IntoIterator&amp;gt;::Item) -&amp;gt; Ordering&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;filter&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(&amp;amp;Self::Item) -&amp;gt; bool&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;filter_map&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(Self::Item) -&amp;gt; Option&amp;lt;B&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;find&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(&amp;amp;Self::Item) -&amp;gt; bool&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_find&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;find_map&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(Self::Item) -&amp;gt; Option&amp;lt;B&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;flat_map&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(Self::Item) -&amp;gt; impl IntoIterator&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;fold&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(B, Self::Item) -&amp;gt; B&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_fold&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;for_each&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(Self::Item)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_for_each&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;inspect&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(&amp;amp;Self::Item)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;is_partitioned&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(Self::Item) -&amp;gt; bool&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;is_sorted_by&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(&amp;amp;Self::Item, &amp;amp;Self::Item) -&amp;gt; Option&amp;lt;Ordering&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;is_sorted_by_key&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(&amp;amp;Self::Item) -&amp;gt; impl PartialOrd&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;map&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(Self::Item) -&amp;gt; B&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;max_by&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(&amp;amp;Self::Item, &amp;amp;Self::Item) -&amp;gt; Ordering&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;max_by_key&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(&amp;amp;Self::Item) -&amp;gt; impl Ord&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;min_by&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(&amp;amp;Self::Item, &amp;amp;Self::Item) -&amp;gt; Ordering&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;min_by_key&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(&amp;amp;Self::Item) -&amp;gt; impl Ord&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;partial_cmp_by&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(Self::Item, &amp;lt;I as IntoIterator&amp;gt;::Item) -&amp;gt; Option&amp;lt;Ordering&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;partition&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(&amp;amp;Self::Item) -&amp;gt; bool&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;partition_in_place&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(&amp;amp;T) -&amp;gt; bool&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;position&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(Self::Item) -&amp;gt; bool&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;rposition&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(Self::Item) -&amp;gt; bool&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;scan&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(&amp;amp;mut St, Self::Item) -&amp;gt; Option&amp;lt;B&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;skip_while&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(&amp;amp;Self::Item) -&amp;gt; bool&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;take_while&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(&amp;amp;Self::Item) -&amp;gt; bool&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;try_find&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(&amp;amp;Self::Item) -&amp;gt; impl Try&amp;lt;Ok = bool, Error = E&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;try_fold&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(B, Self::Item) -&amp;gt; impl Try&amp;lt;Ok = B&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;try_for_each&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;FnMut(Self::Item) -&amp;gt; impl Try&amp;lt;Ok = ()&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Out of the 63 current stream adapters available, 30 take closures. Of those
30 adapters only 10 can bubble up a &lt;code&gt;Result&lt;&#x2F;code&gt; or have a counterpart that can
do so. That means that 20 methods, or almost a third of the functionality in
&lt;code&gt;Iterator&lt;&#x2F;code&gt; is currently incompatible with fallible operations.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;implementing-missing-adapters&quot;&gt;Implementing missing adapters&lt;&#x2F;h2&gt;
&lt;p&gt;If we wanted to expose the full range of functionality to fallible iterators,
we would likely need to create &lt;code&gt;try_&lt;&#x2F;code&gt; counterparts to the stream adapters
that currently don&#x27;t support it. This is a list of methods and their proposed
fallible counterparts:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Name&lt;&#x2F;th&gt;&lt;th&gt;Fallible counterpart&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;all&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_all&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;any&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_any&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;cmp_by&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_cmp_any&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;eq_by&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_eq_by&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;filter&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_filter&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;inspect&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_inspect&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;is_partitioned&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_is_partitioned&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;is_sorted_by&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_is_sorted_by&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;is_sorted_by_key&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_is_sorted_by_key&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;max_by&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_max_by&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;max_by_key&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_max_by_key&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;min_by&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_min_by&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;min_by_key&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_min_by_key&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;partial_cmp_by&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_partial_cmp_by&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;partition&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_partition&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;partition_in_place&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_partition_in_place&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;position&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_position&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;rposition&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_rposition&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;scan&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_scan&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;skip_while&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_skip_while&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;take_while&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;try_take_while&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve looked at the various adapters &lt;code&gt;std::iter::Iterator&lt;&#x2F;code&gt;
provides, talked about error handling, and surveyed how existing methods
interact with them. Finally we&#x27;ve provided an overview of methods that
currently don&#x27;t provide support for the try operator in the closure body, and
which counterparts would need to be added so they could work.&lt;&#x2F;p&gt;
&lt;p&gt;Some readers may be wondering now whether it&#x27;s actually worth adding several
new methods to &lt;code&gt;Iterator&lt;&#x2F;code&gt;, and whether that&#x27;s perhaps too much. But I don&#x27;t
think counting methods is a particularly effective way of making API
decisions &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#lol&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Instead it&#x27;s better to look at overall cohesion and
usability.&lt;&#x2F;p&gt;
&lt;p&gt;I think a more useful framework for answering this design question
is to ask: &quot;Are we okay that a third of the methods on iterator only work
some of the time?&quot; I think the answer there should be a clear &quot;no&quot;. If a
person wants to perform IO operations while filtering some input, they should
be able to, without needing to start over and write manual loops from scratch.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;lol&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;I&#x27;ve definitely done this a lot in the past, and I was wrong for
doing so. Growth.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</description>
        </item>
        <item>
            <title>Nine Patches</title>
            <pubDate>Tue, 07 Apr 2020 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/nine-patches/</link>
            <guid>https://blog.yoshuawuyts.com/nine-patches/</guid>
            <description>&lt;p&gt;Contributing to &lt;code&gt;rust-lang&#x2F;rust&lt;&#x2F;code&gt; has been a long-standing desire of mine.
It&#x27;s a central of software that has enabled a lot of my work, and being able
to contribute directly back to it felt like something I wanted to do
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#contributing&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;contributing&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Contributing in this context leans mostly towards
&quot;contributing code&quot;. That&#x27;s not the only kind of contributions possible
though; the &lt;a href=&quot;https:&#x2F;&#x2F;scuttlebutt.nz&#x2F;&quot;&gt;Scuttlebutt community&lt;&#x2F;a&gt; has actively
been trying to shift the thinking around &quot;contributions&quot; to include everyone
in the process: people drafting issues, managing issues, organizing meetings,
reviewing, and writing code. I believe they keep a spreadsheet somewhere to
properly credit folks for their contributions. But yeah in my case, I wanted
to contribute patches to &lt;code&gt;rust-lang&#x2F;rust&lt;&#x2F;code&gt; because it seemed like fun.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Becuase &lt;code&gt;rust-lang&#x2F;rust&lt;&#x2F;code&gt; is such a big project (100.000+ commits, 2500+
contributors) I felt I wanted to be super careful about any contributions. So
my first attempt to contribute was over a year ago and I tried to contribute
the &lt;code&gt;Num::leading_ones&lt;&#x2F;code&gt; and &lt;code&gt;Num::trailing_ones&lt;&#x2F;code&gt; APIs. I &lt;a href=&quot;https:&#x2F;&#x2F;internals.rust-lang.org&#x2F;t&#x2F;pre-rfc-leading-ones-trailing-ones&#x2F;8762&quot;&gt;drafted an
RFC&lt;&#x2F;a&gt;,
then &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;pull&#x2F;55715&quot;&gt;tried submitting an
implementation&lt;&#x2F;a&gt;, but life got
in the way and I didn&#x27;t see it through to completion.&lt;&#x2F;p&gt;
&lt;p&gt;In January of this year someone else went ahead and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;57969&quot;&gt;landed a PR for the same
features feature&lt;&#x2F;a&gt; and that
inspired me. So last weekend I had some time to spare, and figured I&#x27;d go
ahead and try sending in my first patch! It&#x27;s been 4 days since, and I&#x27;ve now
sent through 9 patches. Not all are merged, but I figured it&#x27;d be fun to talk
about them still!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;1-fix-a-broken-link&quot;&gt;1. Fix a broken link&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;pull&#x2F;70730&quot;&gt;#70730&lt;&#x2F;a&gt;. I noticed a broken
link in the docs, and figured fixing it would both be easy and guaranteed to
land. A perfect first patch! So I set out to check out the compiler, got it
to build, fixed the docs and submitted a patch. And lo and behold: it got
merged in under a day!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2-arc-incr-decr-strong-count&quot;&gt;2. Arc::{incr,decr}_strong_count&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;pull&#x2F;70733&quot;&gt;#70733&lt;&#x2F;a&gt;.
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;sync&#x2F;struct.Arc.html&quot;&gt;&lt;code&gt;std::sync::Arc&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is an
&quot;Atomic Reference Counter&quot; that&#x27;s provided by the stdlib. A common way to use
it is to wrap some structure you want to share between threads in it, and call
&lt;code&gt;clone&lt;&#x2F;code&gt; on it to get owned copies that point to the same structure.
However there&#x27;s another use for it: to create an atomic reference counter for
use in other structures. A common structure where this comes in useful for is
when manually constructing
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;task&#x2F;struct.Waker.html&quot;&gt;&lt;code&gt;Waker&lt;&#x2F;code&gt;s&lt;&#x2F;a&gt;: one of the
core building blocks used in &lt;code&gt;async&#x2F;await&lt;&#x2F;code&gt;. Each waker needs to implement
&lt;code&gt;Clone&lt;&#x2F;code&gt;, and encapsulates a
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;task&#x2F;struct.RawWaker.html&quot;&gt;&lt;code&gt;RawWaker&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Because of reasons the best way to use an &lt;code&gt;Arc&lt;&#x2F;code&gt; for these kinds of cases is
to access it through a pointer. But unfortunately &lt;code&gt;Arc&lt;&#x2F;code&gt; doesn&#x27;t provide
manual ways to access its internal counters so a lot of code uses tricks to
increment &#x2F; decrement counters through pointers:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Increment the strong reference count
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; arc: Arc&amp;lt;W&amp;gt; = Arc::from_raw(ptr);
&lt;&#x2F;span&gt;&lt;span&gt;mem::forget(Arc::clone(&amp;amp;arc));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Decrement the strong reference count
&lt;&#x2F;span&gt;&lt;span&gt;mem::drop(Arc::from_raw(ptr));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is not ideal for many reasons; it&#x27;s easy to get issues such as double
frees, and the consequences lead to memory unsafety. Instead having methods
to change the reference counts without any of those risks would be
desireable. And &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Mark-Simulacrum&quot;&gt;@mark-simulacrum&lt;&#x2F;a&gt; came
up with a really nice design for this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Increment the strong reference count
&lt;&#x2F;span&gt;&lt;span&gt;Arc::incr_strong_count(ptr);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Decrement the strong reference count
&lt;&#x2F;span&gt;&lt;span&gt;Arc::decr_strong_count(ptr);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This allows incrementing &#x2F; decrementing the Arc refcounts through pointers,
which is a big win over manually trying to do things with atomics, or
manually trying to mutate the refcounts.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-add-slice-fill&quot;&gt;3. Add slice::fill&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;pull&#x2F;70752&quot;&gt;#70752&lt;&#x2F;a&gt;. This patch adds a way
to uniformly assign a value to a region of memory in Rust. A while ago I was
working with Ryan Levick on &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rylev&#x2F;remem&quot;&gt;&lt;code&gt;remem&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and
during one of the experiments we noticed that there was no convenient API to
write zeroes into a memory region. What we ended up doing was a &lt;code&gt;for&lt;&#x2F;code&gt; loop
and writing values one-by-one &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#zeroize&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;zeroize&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;There are many more considerations around zeroing memory. I
implore you to check out &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;zeroize&#x2F;1.1.0&#x2F;zeroize&#x2F;&quot;&gt;&lt;code&gt;zeroize&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
to see some of the other considerations beyond basic convenience and
performance. I do hope someday we&#x27;ll see parts of it come over into std.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This was patch was merged a few days ago, and is &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nightly&#x2F;std&#x2F;primitive.slice.html#method.fill&quot;&gt;now available on
nightly&lt;&#x2F;a&gt;.
So basically what this provides is that instead of doing this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; buf = vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; val in buf {
&lt;&#x2F;span&gt;&lt;span&gt;    *val = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(buf, vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can now write this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; buf = vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;buf.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;fill&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(buf, vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It comes with the added benefit of using
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;clone&#x2F;trait.Clone.html#method.clone_from&quot;&gt;&lt;code&gt;Clone::clone_from&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
under the hood which enables memory reuse in certain cases. Also in the case
of writing &lt;code&gt;u8&lt;&#x2F;code&gt; or &lt;code&gt;u16&lt;&#x2F;code&gt; it optimizes down to a single
&lt;a href=&quot;https:&#x2F;&#x2F;linux.die.net&#x2F;man&#x2F;3&#x2F;memset&quot;&gt;&lt;code&gt;memset(3)&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; call!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;4-add-conversion-from-arc-for-waker&quot;&gt;4. Add conversion from Arc&lt;Fn&gt; for Waker.&lt;&#x2F;h2&gt;
&lt;p&gt;The idea was that using the new &lt;code&gt;Wake&lt;&#x2F;code&gt; trait, instead of having to write this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; With the Wake trait
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::task::{Waker, Wake};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;crossbeam::sync::{Unparker};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;BlockOnWaker {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;unparker&lt;&#x2F;span&gt;&lt;span&gt;: Unparker,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Wake &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;BlockOnWaker {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;wake&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Arc&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.unparker.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unpark&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;block_on&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;F: Future&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;future&lt;&#x2F;span&gt;&lt;span&gt;: F) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;F::&lt;&#x2F;span&gt;&lt;span&gt;Output {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; unparker = ...;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; waker = Waker::from(Arc::new(BlockOnWaker { unparker }));
&lt;&#x2F;span&gt;&lt;span&gt;    ...
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In basic cases you could just write this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; With this API
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::task::Waker;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;block_on&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;F: Future&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;future&lt;&#x2F;span&gt;&lt;span&gt;: F) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;F::&lt;&#x2F;span&gt;&lt;span&gt;Output {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; unparker = ...;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; waker = Waker::from(Arc::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;|| unparker.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unpark&lt;&#x2F;span&gt;&lt;span&gt;()));
&lt;&#x2F;span&gt;&lt;span&gt;    ...
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But for real-world use this is not great, and so we decided it was probably
better to not merge it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;5-add-bufread-read-while&quot;&gt;5. Add BufRead::read_while&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;pull&#x2F;70772&quot;&gt;#70772&lt;&#x2F;a&gt;. I recently got
interested in parsers, and &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;byte-ordered-stream-parsing&#x2F;&quot;&gt;wrote about my
experience&lt;&#x2F;a&gt;. One
of the APIs that came out of this was &lt;code&gt;BufRead::read_while&lt;&#x2F;code&gt;, which forms a
counterpart to &lt;code&gt;BufRead::read_until&lt;&#x2F;code&gt;. The idea is that we can read bytes into
a buffer as long as a &quot;predicate&quot; (a closure) returns true:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::io::{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, BufRead};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; cursor = io::Cursor::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;lorem-ipsum&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; buf = vec![];
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;cursor.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_while&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; buf, |&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;| b != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;)?;
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(buf, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;lorem&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This patch hasn&#x27;t been merged yet, and there&#x27;s a question about whether
&lt;code&gt;Read::take_while&lt;&#x2F;code&gt; could perhaps be a better fit. But overall I&#x27;m happy we&#x27;re
talking about ways to make reading bytes streams easier, which in turn will
make it easier to write streaming parsers.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;6-add-ready-macro&quot;&gt;6. Add ready! macro&lt;&#x2F;h2&gt;
&lt;p&gt;When writing futures by hand (or streams, or async read and write impls) one
of the core building blocks is
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;task&#x2F;enum.Poll.html&quot;&gt;&lt;code&gt;Poll&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. This enum
behaves the same as &lt;code&gt;Option&lt;&#x2F;code&gt;, but instead of talking about &quot;some&quot; and
&quot;none&quot; we talk about &quot;ready&quot; and &quot;pending&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Because of reasons &lt;code&gt;Try&lt;&#x2F;code&gt; isn&#x27;t implemented directly on &lt;code&gt;Poll&lt;&#x2F;code&gt;, so simply
doing &lt;code&gt;?&lt;&#x2F;code&gt; on it doesn&#x27;t work to return early. Instead the whole ecosystem
relies on a &lt;code&gt;Poll&lt;&#x2F;code&gt; equivalent of the &lt;code&gt;try!&lt;&#x2F;code&gt; macro: &lt;code&gt;ready!&lt;&#x2F;code&gt;. This 5-line macro
is relied on by every single project that implements futures, and is even
part of &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-core&#x2F;&quot;&gt;&lt;code&gt;futures-core&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This patch introduces it to stdlib, so after that the only API left to
include from &lt;code&gt;futures-core&lt;&#x2F;code&gt; would be &lt;code&gt;Stream&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;core::task::{Context, Poll};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;core::future::Future;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;core::pin::Pin;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;get_num&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;42
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;do_poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; f = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get_num&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; f = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ Pin::new_unchecked(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; f) };
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; num = ready!(f.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(cx));
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ... use num
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    Poll::Ready(())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;7-removed-outdated-comments&quot;&gt;7. Removed outdated comments&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;pull&#x2F;70824&quot;&gt;#70824&lt;&#x2F;a&gt;. While investigating
how to add &lt;code&gt;ready!&lt;&#x2F;code&gt; to std I found some outdated comments that had likely
been moved around by some tooling. This patch removed them since they they
didn&#x27;t really serve any purpose.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;8-add-future&quot;&gt;8. Add future::&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;pull&#x2F;70834&quot;&gt;#70834&lt;&#x2F;a&gt;. This patch adds two
APIs to the &lt;code&gt;future&lt;&#x2F;code&gt; submodule: &lt;code&gt;future::ready&lt;&#x2F;code&gt; and &lt;code&gt;future::pending&lt;&#x2F;code&gt;. Much
like &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;fn.once.html&quot;&gt;&lt;code&gt;std::iter::once&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;fn.empty.html&quot;&gt;&lt;code&gt;std::iter::empty&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; they
allow quickly constructing a type with a certain behavior. &lt;code&gt;future::ready&lt;&#x2F;code&gt;
immediately returns a value. And &lt;code&gt;future::pending&lt;&#x2F;code&gt; &lt;em&gt;never&lt;&#x2F;em&gt; returns a value.&lt;&#x2F;p&gt;
&lt;p&gt;This is particularly useful for tests. Especially since both types implement
&lt;code&gt;Unpin&lt;&#x2F;code&gt; which means we don&#x27;t need to worry about &lt;code&gt;Pin&lt;&#x2F;code&gt; in examples. So the
example we saw in the last section about the &lt;code&gt;ready&lt;&#x2F;code&gt; macro could be written
without using &lt;code&gt;unsafe&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;core::task::{Context, Poll};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;core::future::{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, Future};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;core::pin::Pin;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;do_poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; fut = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;42_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; num = ready!(Pin::new(fut).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(cx));
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ... use num
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    Poll::Ready(())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;9-add-integer&quot;&gt;9. Add Integer::&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;pull&#x2F;70835&quot;&gt;#70835&lt;&#x2F;a&gt;. This was a particular
fun patch set because I got to work with a friend! A while back &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;substack&#x2F;status&#x2F;1236445105197727744&quot;&gt;Substack
tweeted&lt;&#x2F;a&gt; they wish
they had &lt;code&gt;Integer::log2&lt;&#x2F;code&gt; in the stdlib because implementing it by hand
requires a lot of care.&lt;&#x2F;p&gt;
&lt;p&gt;Now that I felt somewhat confident submitting patches to &lt;code&gt;rust-lang&#x2F;rust&lt;&#x2F;code&gt; I
figured this would be a fun, somewhat out-there PR to attempt. We ended up
working together, with me handling submitting the PR and integrating it into
Rust, and Substack making the implementation work.&lt;&#x2F;p&gt;
&lt;p&gt;What this patch enables is to be able to do the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;assert_eq!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1_000_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;log10&lt;&#x2F;span&gt;&lt;span&gt;(), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which doesn&#x27;t look like much; but if you look at the implementation there is
a &lt;em&gt;lot&lt;&#x2F;em&gt; going on to make this work. This is useful because it allows us to
calculate logarithms for much higher numbers than if we had to convert ints
to floats and back, and by providing a arbitrary base &lt;code&gt;log&lt;&#x2F;code&gt; method it also
allows bypassing subtle precision bugs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;The past 4 days have been a lot of fun. I&#x27;m happy I got to implement the
patches that I did, and excited some of them have even landed on nightly.&lt;&#x2F;p&gt;
&lt;p&gt;Generally the experience submitting patches was positive. Getting up and
running took some work (hi cmake, python, x.py). But once I was a few patches
in I mostly knew how to go about it.&lt;&#x2F;p&gt;
&lt;p&gt;This has been an overview of me submitting a few patches. It was fun!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>State Machines: Introduction</title>
            <pubDate>Mon, 30 Mar 2020 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/state-machines/</link>
            <guid>https://blog.yoshuawuyts.com/state-machines/</guid>
            <description>&lt;p&gt;Every now and then I like to think about topics that don&#x27;t directly relate to
my daily work. One of those topics has been parsers: back in January I wrote
about &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;byte-ordered-stream-parsing&#x2F;&quot;&gt;byte-ordered
stream parsing&lt;&#x2F;a&gt;
and how I think we can improve streaming parsing in Rust with a small set of
API additions.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve recently been thinking of how to improve beyond that, and one topic of
interest has been state machines. &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#parsers&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; Much of parsing logic includes sequences
of: &quot;If you see character X, read until character Y, then look for character
Z.&quot; This sequence can best be described as a &quot;transition between states&quot;, and
state machines are a common technique&#x2F;structure&#x2F;pattern to describe these. &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#quick&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;parsers&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Back in December I was exploring parsers, and got a feel for the
difference between &quot;parser combinators&quot; and &quot;parser generators&quot;. &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;mountain_ghosts&#x2F;status&#x2F;1204061356661624832&quot;&gt;Mountain
Ghosts (James
Coglan)&lt;&#x2F;a&gt;
pointed out on Twitter that there&#x27;s another variant of parsers: Prolog&#x27;s
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Definite_clause_grammar&quot;&gt;&quot;Definite clause
grammars&quot;&lt;&#x2F;a&gt;. After
reading the Wiki entry on it it felt like it definitely looked like state
machines. And I happen to know that the compiler &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;chalk&quot;&gt;uses Prolog for type
resolution&lt;&#x2F;a&gt;. So I got to wonder: if Rust
has state machines as part of the language, would that get us closer to being
able to express parsers in a manner not too dissimilar from definite clause
grammars? I bet someone with more knowledge about these things could say more
on this.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;quick&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;It&#x27;s 23:05 on a Monday here. I&#x27;ve been thinking about state
machines all weekend for no good reason. So I&#x27;m writing this post in a single
take to get it out of my mind and into a structured form before I lose my
mind.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;what-are-state-machines&quot;&gt;What are state machines?&lt;&#x2F;h2&gt;
&lt;p&gt;In Rust &lt;em&gt;states&lt;&#x2F;em&gt; are often described as enums: a boolean can be &lt;code&gt;true&lt;&#x2F;code&gt; or
&lt;code&gt;false&lt;&#x2F;code&gt;. An &lt;code&gt;Option&lt;&#x2F;code&gt; can be &lt;code&gt;Some&lt;&#x2F;code&gt; or &lt;code&gt;None&lt;&#x2F;code&gt;. &lt;em&gt;State machines&lt;&#x2F;em&gt; describe
the relations between states. For example a traffic light can go from red to
green, but never from red to yellow - it has to pass through green first &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#yellow&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;yellow&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;In Germany traffic lights go &lt;code&gt;green -&amp;gt; yellow -&amp;gt; red -&amp;gt; yellow -&amp;gt; green&lt;&#x2F;code&gt;, but let&#x27;s pretend they&#x27;re only &lt;code&gt;green -&amp;gt; yellow -&amp;gt; red -&amp;gt; green&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;img src=&quot;&#x2F;assets&#x2F;graphs&#x2F;cyclic_graph.jpg&quot; alt=&quot;cyclic graph&quot; style=&quot;max-width:300px&quot;&gt;
&lt;p&gt;&lt;em&gt;A graph depicting 4 states and 5 transitions, drawn by
&lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;_lrlna&quot;&gt;@_lrlna&lt;&#x2F;a&gt; for our
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;graphs&#x2F;&quot;&gt;&quot;Graphs&quot;&lt;&#x2F;a&gt; post.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;State machines not only encode which transitions are &lt;em&gt;valid&lt;&#x2F;em&gt;, in doing so
they also encode which transitions are &lt;em&gt;invalid&lt;&#x2F;em&gt;. For example in a financial
system there might be some important check we need to perform before we
declare success. A state machine would allows us to encode that the &quot;success&quot;
state must be preceded by a &quot;verifying&quot; state.&lt;&#x2F;p&gt;
&lt;p&gt;An interesting property that I personally value a lot in state machines is
how much utility they provide in active codebases. Instead of encoding
relations in boolean logic, they can be extracted into their own site. And in
doing so they become more resilient against emergent bugs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;state-machines-in-rust-today&quot;&gt;State machines in Rust today&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we&#x27;ve looked at what state machines are, and hopefully convinced you
of their usefulness, let&#x27;s take a look at how to implement them in Rust. Much
of what I&#x27;m saying here was inspired by &lt;a href=&quot;https:&#x2F;&#x2F;hoverbear.org&#x2F;blog&#x2F;rust-state-machine-pattern&quot;&gt;Hoverbear&#x27;s &quot;Rust state machine
pattern&quot; post&lt;&#x2F;a&gt;, which
I recommend reading.&lt;&#x2F;p&gt;
&lt;p&gt;The ideal scenario for a state machine is to encode it entirely at compile
time: that way if our program compiles we can be sure that the only state
transitions occurring are the ones we&#x27;ve defined as being allowed.&lt;&#x2F;p&gt;
&lt;p&gt;The way to make this work in Rust today is through type params. If we take
our &quot;traffic light&quot; example we mentioned earlier, we could encode it in Rust
today as:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Debug)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Green;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Debug)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Yellow;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Debug)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Red;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Debug)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;State&amp;lt;S&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;_inner&lt;&#x2F;span&gt;&lt;span&gt;: S
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;State&amp;lt;Green&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; State&amp;lt;Green&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        State { _inner: Green{} }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;State&amp;lt;Green&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; State&amp;lt;Yellow&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        State { _inner: Yellow {} }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;State&amp;lt;Yellow&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; State&amp;lt;Red&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        State { _inner: Red {} }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;State&amp;lt;Red&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; State&amp;lt;Green&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        State { _inner: Green {} }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; state = State::new(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; green
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; yellow
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; red
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; green
&lt;&#x2F;span&gt;&lt;span&gt;    dbg!(state);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=stable&amp;amp;mode=debug&amp;amp;edition=2018&amp;amp;gist=9ac3f0d23b98a28dd94e12fb0f1a30ab&quot;&gt;Link to playground&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As you can see calling &lt;code&gt;next&lt;&#x2F;code&gt; changes the state from one variant to another.
And even though the method might look the same and exist on the same struct:
they&#x27;re very much different.&lt;&#x2F;p&gt;
&lt;p&gt;If we try and call a method with the incorrect state the compiler will
provide some really good messages around this. Say, we wanted to make sure
bikes can only go when the light is green. The following example tries to
allow bikes in a &quot;red&quot; state, which provides a nice compilation error.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; state = State::new(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; green
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; yellow
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; red
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;allow_bikes&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;state);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; green
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;allow_bikes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;state&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;State&amp;lt;Green&amp;gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    todo!();
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;Compiling playground v0.0.1 (&#x2F;playground)
&lt;&#x2F;span&gt;&lt;span&gt;error[E0308]: mismatched types
&lt;&#x2F;span&gt;&lt;span&gt;  --&amp;gt; src&#x2F;main.rs:42:17
&lt;&#x2F;span&gt;&lt;span&gt;   |
&lt;&#x2F;span&gt;&lt;span&gt;42 |     allow_bikes(&amp;amp;state);
&lt;&#x2F;span&gt;&lt;span&gt;   |                 ^^^^^^ expected struct `Green`, found struct `Red`
&lt;&#x2F;span&gt;&lt;span&gt;   |
&lt;&#x2F;span&gt;&lt;span&gt;   = note: expected reference `&amp;amp;State&amp;lt;Green&amp;gt;`
&lt;&#x2F;span&gt;&lt;span&gt;              found reference `&amp;amp;State&amp;lt;Red&amp;gt;`
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;error: aborting due to previous error
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However one big limitation of this is that this pattern cannot store the
state inside another struct; it can only exist on the stack this way. So we
cannot do the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Foo&amp;lt;S&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;state&lt;&#x2F;span&gt;&lt;span&gt;: State&amp;lt;S&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The moment we initialize &lt;code&gt;Foo&lt;&#x2F;code&gt; to take e.g. &lt;code&gt;Green&lt;&#x2F;code&gt; as its parameter, it can
now no longer switch to &lt;code&gt;Red&lt;&#x2F;code&gt; in safe Rust. This is what enums are for, and
unfortunately we can&#x27;t use those here.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Promising state machine ecosystem crates to check out that work today are:
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;machine&#x2F;0.3.0&#x2F;machine&#x2F;&quot;&gt;machine&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;state_machine_future&#x2F;0.2.0&#x2F;state_machine_future&#x2F;&quot;&gt;state_machine_future&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;future-directions&quot;&gt;Future Directions&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;p-org&#x2F;P&#x2F;wiki&#x2F;PingPong-program&quot;&gt;P programming
language&lt;&#x2F;a&gt; has state
machines as a first-class construct in the language. It defines states using
the &lt;code&gt;state&lt;&#x2F;code&gt; keyword and uses &lt;code&gt;on&lt;&#x2F;code&gt;, &lt;code&gt;goto&lt;&#x2F;code&gt;, and &lt;code&gt;raise&lt;&#x2F;code&gt; keywords to switch
between states &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#plaid&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. After seeing this I got to wonder: &quot;Would it be possible for
Rust to have first-class state machines as part of the language with minimal
changes?&quot; And well, I think, maybe?&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;plaid&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;I also found the &lt;a href=&quot;http:&#x2F;&#x2F;plaid-lang.org&quot;&gt;Plaid language&lt;&#x2F;a&gt; which
talks about state machines a bunch, but most of it is written as PDFs, and
source tarballs, so I didn&#x27;t really research it further.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;em&gt;Before we continue, the usual disclaimer: &lt;strong&gt;I&#x27;m not a language designer nor
on any lang team. This is all speculative.&lt;&#x2F;strong&gt; This all comes from a place of
interest, and am by no means an authority on the matter.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;So the pitch is: &quot;If enums are a way of describing state, and methods are a
way of describing behavior, would it be possible to put the two together to
create a state machine?&quot;&lt;&#x2F;p&gt;
&lt;p&gt;Currently enums have the limitation that its members aren&#x27;t fully qualified
types. But &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;pull&#x2F;2593&quot;&gt;imagine for a second we
they were&lt;&#x2F;a&gt;. What that would mean
is that we could reason about enum members as if they were full types.&lt;&#x2F;p&gt;
&lt;p&gt;Now imagine we could use enum members as arbitrary self types, and return
enum members from functions &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#specialization&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. We could then rewrite our
traffic example like this:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;specialization&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;This probably needs specialization too. Insert hand waving
&#x2F; jazz hands here.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;State {
&lt;&#x2F;span&gt;&lt;span&gt;    Green,
&lt;&#x2F;span&gt;&lt;span&gt;    Yellow,
&lt;&#x2F;span&gt;&lt;span&gt;    Red,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;State {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Green
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Yellow {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Yellow
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Yellow) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Red {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Red
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Red) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Green {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;::Green
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; state = State::new(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; green
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; yellow
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; red
&lt;&#x2F;span&gt;&lt;span&gt;    state = state.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; green
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see this nicely tucks state back into a single enum, and uses
named transitions to switch between one state to the other. This makes enums
the single source of both &lt;em&gt;states&lt;&#x2F;em&gt; and &lt;em&gt;transitions between states&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Additionally methods could not only return &lt;code&gt;Self&lt;&#x2F;code&gt;: they could return results
or futures as well; enabling various kinds of transitions to occur. And
diagnostics could probably be quite good here as well:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;Compiling playground v0.0.1 (&#x2F;playground)
&lt;&#x2F;span&gt;&lt;span&gt;error[E0308]: mismatched types
&lt;&#x2F;span&gt;&lt;span&gt;  --&amp;gt; src&#x2F;main.rs:42:17
&lt;&#x2F;span&gt;&lt;span&gt;   |
&lt;&#x2F;span&gt;&lt;span&gt;42 |     allow_bikes(&amp;amp;state);
&lt;&#x2F;span&gt;&lt;span&gt;   |                 ^^^^^^ expected `State::Green`, found `State::Red`
&lt;&#x2F;span&gt;&lt;span&gt;   |
&lt;&#x2F;span&gt;&lt;span&gt;   = note: expected reference `&amp;amp;State::Green`
&lt;&#x2F;span&gt;&lt;span&gt;              found reference `&amp;amp;State::Red`
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;error: aborting due to previous error
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However, there are a lot of big speculative &quot;if&quot;&#x27;s attached here. Is it
possible to fully reason about enum members in this way? Can this even be
made sound? Implementing this would leave a lot of questions that need to be
answered by people with domain expertise.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this rather hastily written post we&#x27;ve shared what state machines are, how
they can be authored in Rust today, their limitations, and speculated on
language extensions to make them easier to author.&lt;&#x2F;p&gt;
&lt;p&gt;In principle it&#x27;s already possible to write state machines in Rust today. The
compiler will verify them for you, and provide helpful messages when things
go wrong. It&#x27;s somewhat of a testatement to how useful linear types are.
However they come with severe limitations, and don&#x27;t always feel the most
natural to write.&lt;&#x2F;p&gt;
&lt;p&gt;What I like about the future direction I&#x27;ve sketched in this post is that it
&lt;em&gt;looks&lt;&#x2F;em&gt; like a fairly natural extension to today&#x27;s Rust. But would enable
compiler-checked general-purpose state machines to exist in Rust, which is
something that &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;hillelogram&#x2F;status&#x2F;1243608940484734976&quot;&gt;doesn&#x27;t seem common in programming
languages&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;What I like about the direction we&#x27;ve outlined in this post so far is that it
sketches something that feels like a fairly natural extension to what Rust is
like today.&lt;&#x2F;p&gt;
&lt;p&gt;Maybe this post will prove to be inspirational for first-class state machines
in Rust at some point in the future. Or possibly I&#x27;m saying things that are
strictly impossible. Either way, this has been a fun thought exercise, and
figured it might be fun to share &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#share&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Thanks for reading&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#times&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;!&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;share&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;As I&#x27;ve been trying and not lose my mind; I&#x27;ve been thinking about
state machines for 72 hours and &lt;em&gt;needed&lt;&#x2F;em&gt; to get this out of my system.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;times&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;In these trying times.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</description>
        </item>
        <item>
            <title>parallel-stream</title>
            <pubDate>Tue, 17 Mar 2020 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/parallel-stream/</link>
            <guid>https://blog.yoshuawuyts.com/parallel-stream/</guid>
            <description>&lt;p&gt;Last weekend I released &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;parallel-stream&quot;&gt;parallel-stream&lt;&#x2F;a&gt;, a
data parallelism library for async std. It&#x27;s to
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.5.0&#x2F;async_std&#x2F;stream&#x2F;index.html&quot;&gt;streams&lt;&#x2F;a&gt;, the
way &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rayon&quot;&gt;rayon&lt;&#x2F;a&gt; is to
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;index.html&quot;&gt;iterators&lt;&#x2F;a&gt;. This is an
implementation of a design &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;streams-concurrency&#x2F;&quot;&gt;I wrote about
earlier&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The way &lt;code&gt;parallel-stream&lt;&#x2F;code&gt; works is that instead of calling
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.5.0&#x2F;async_std&#x2F;stream&#x2F;trait.IntoStream.html#tymethod.into_stream&quot;&gt;&lt;code&gt;into_stream&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to create a sequential stream
you can call
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;parallel-stream&#x2F;2.1.1&#x2F;parallel_stream&#x2F;trait.IntoParallelStream.html#tymethod.into_par_stream&quot;&gt;&lt;code&gt;into_par_stream&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
to create a &quot;parallel&quot; stream instead. This means that each item in the
stream will be operated on in a new
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.5.0&#x2F;async_std&#x2F;task&#x2F;index.html#the-task-model&quot;&gt;task&lt;&#x2F;a&gt;,
which enables multi-core processing of items backed by a thread pool.&lt;&#x2F;p&gt;
&lt;p&gt;For example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;parallel_stream::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;async_std&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create a vec of numbers to square.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; v = vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Convert the vec into a parallel stream and collect each item into a vector.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; res: Vec&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; = v
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_par_stream&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;| async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{ n * n })
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;        .await;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Items are stored as soon as they&amp;#39;re ready so we need to sort them.
&lt;&#x2F;span&gt;&lt;span&gt;    res.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;sort&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    assert_eq!(res, vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;9&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This model should make it easy to quickly process streams in parallel where
previously it would&#x27;ve required significant effort to setup.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;parallel-stream&lt;&#x2F;code&gt; today only provides the basics: &lt;code&gt;map&lt;&#x2F;code&gt;, &lt;code&gt;for_each&lt;&#x2F;code&gt;, &lt;code&gt;next&lt;&#x2F;code&gt;,
and &lt;code&gt;collect&lt;&#x2F;code&gt;. This was enough to prove it works, and should cover the 90%
use case for most people.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;comparing-to-other-libraries&quot;&gt;Comparing to other libraries&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;parallel-stream&lt;&#x2F;code&gt; does not inherently enable anything that couldn&#x27;t be done
before. Instead it makes existing capabilities much more accessible, which
increases the likelyhood they&#x27;ll be used, which in turn is good for
performance.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;rayon&quot;&gt;Rayon&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rayon&#x2F;&quot;&gt;Rayon&lt;&#x2F;a&gt; is a data parallelism library built for
synchronous Rust, powered by an underlying thread pool. async-std manages a
thread pool as well, but the key difference with Rayon is that async-std (and
futures) are optimized for &lt;em&gt;latency&lt;&#x2F;em&gt;, while Rayon is optimized for
&lt;em&gt;throughput&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;As a rule of thumb: if you want to speed up doing heavy calculations you
probably want to use Rayon. If you want to parallelize network requests
consider using &lt;code&gt;parallel-stream&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; rayon(parallel): convert a vec into a parallel iterator.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Map each item in the iterator, and collect into a vec.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res: Vec&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; = vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_par_iter&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;| n * n )
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;| n + n )
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; parallel-stream(parallel): convert a vec into a parallel stream.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Map each item in the stream, and collect into a vec.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res: Vec&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; = vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_par_stream&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;| async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{ n * n })
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;| async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{ n + n })
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .await;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;futures&quot;&gt;Futures&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;&quot;&gt;&lt;code&gt;futures&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; provides several abstractions for
parallelizing streams. These include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;stream::futures_unordered&lt;&#x2F;code&gt;: a &lt;code&gt;Set&lt;&#x2F;code&gt; of futures that can resolve in any order..&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;StreamExt::for_each_concurrent&lt;&#x2F;code&gt;: a concurrent version of &lt;code&gt;Stream::for_each&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;StreamExt::buffer_unordered&lt;&#x2F;code&gt;: buffer up to &lt;code&gt;n&lt;&#x2F;code&gt; futures from a stream simulatenously.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;These methods provide the ability to process multiple items from a stream at
the same time. But by themselves they don&#x27;t schedule work on multiple cores:
they need to be combined with &lt;code&gt;task::spawn&lt;&#x2F;code&gt; in order to do that.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; futures-rs(parallel): convert a vec into a stream. Then map the 
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; stream to a stream of futures (tasks). Then process
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; all of them in parallel, and collect into a vec.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res: Vec&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; = stream::iter(vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;])
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;| task::spawn(async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{ n * n })
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fut&lt;&#x2F;span&gt;&lt;span&gt;| fut.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;| n + n))
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;buffer_unordered&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MAX&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .await;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; parallel-stream(parallel): convert a vec into a parallel stream.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Map each item in the stream, and collect into a vec.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res: Vec&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; = vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_par_stream&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;| async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{ n * n })
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;| async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{ n + n })
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .await;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see both approaches are about the same length, yet they are quite
different. The core difference lies in how tasks are spawned: &lt;code&gt;futures-rs&lt;&#x2F;code&gt;
has a two-step process of converting values into tasks, taking their handles,
and then awaiting those handles in parallel.&lt;&#x2F;p&gt;
&lt;p&gt;While &lt;code&gt;parallel-stream&lt;&#x2F;code&gt; only requires to be initialized once, and then all
future operations on it can be assumed to be parallel. This is especially
noticable when chaining multiple stream adapters.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;configuring-parallelism-limits&quot;&gt;Configuring parallelism limits&lt;&#x2F;h2&gt;
&lt;p&gt;Currently &lt;code&gt;parallel-stream&lt;&#x2F;code&gt; assumes all tasks in the stream will be spawned
in parallel, and doesn&#x27;t impose any limit on how many are running at the same
time. However in practice systems have very real limits, and being able to
configure maximum concurrency is useful.&lt;&#x2F;p&gt;
&lt;p&gt;To that extent we&#x27;ve introduced the &lt;code&gt;limit&lt;&#x2F;code&gt; method as part of the trait,
which governs concurrency &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#wip&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. The idea is that setting a maximum
concurrency would be matter of calling &lt;code&gt;limit&lt;&#x2F;code&gt; on the stream chain:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res: Vec&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; = vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_par_stream&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;limit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Process up to 2 items at the same time.
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;| async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{ n * n })
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .await;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;wip&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;This method exists, but the implementation inside the stream adapters is still a work in progress.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This rougly corresponds to the &lt;code&gt;limit&lt;&#x2F;code&gt; param in
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.3.4&#x2F;futures&#x2F;stream&#x2F;trait.StreamExt.html#method.for_each_concurrent&quot;&gt;&lt;code&gt;futures::stream::Stream::for_each_concurrent&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
and the &lt;code&gt;n&lt;&#x2F;code&gt; parameter in
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.3.4&#x2F;futures&#x2F;stream&#x2F;trait.StreamExt.html#method.buffer_unordered&quot;&gt;&lt;code&gt;futures::stream::Stream::buffer_unordered&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;configuring-ordering&quot;&gt;Configuring ordering&lt;&#x2F;h2&gt;
&lt;p&gt;Like its name implies &lt;code&gt;buffer_unordered&lt;&#x2F;code&gt; has a counterpart: &lt;code&gt;buffer_ordered&lt;&#x2F;code&gt;.
Instead of returning items as soon as they&#x27;re ready, it returns items in
order (but still processes them in parallel).&lt;&#x2F;p&gt;
&lt;p&gt;As you&#x27;ve seen in the examples so far, we&#x27;ve been calling &lt;code&gt;Vec::order&lt;&#x2F;code&gt; after
having finished &lt;code&gt;collect&lt;&#x2F;code&gt;ing items. This generally only works for &lt;em&gt;finite&lt;&#x2F;em&gt;
streams where all items can fit in memory. If a stream is &lt;em&gt;infinite&lt;&#x2F;em&gt;, or the
full contents of the stream can&#x27;t fit in memory, this doesn&#x27;t work. Instead
it&#x27;d be better if items could be sorted on the spot, which would result in
much more efficient use of memory.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;parallel-stream&lt;&#x2F;code&gt; doesn&#x27;t support this yet. It&#x27;s somewhat involved to
implement, and would require resolving
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;async-rs&#x2F;parallel-stream&#x2F;issues&#x2F;4&quot;&gt;issue #4&lt;&#x2F;a&gt; first. But
the API would likely end up looking something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res: Vec&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; = vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_par_stream&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;order&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Return items from the stream in order.
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;| async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{ n * n })
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .await;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Another reason why ordering is not enabled by default is because it uses more
memory for cases when ordering is not important. And since items are now
returned in order, it increases overall latency. Which is often not what you
want when using &lt;code&gt;async&#x2F;await&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Together with the &lt;code&gt;limit&lt;&#x2F;code&gt; method this functionality would provide careful
control of how much work can be done at the same time, and whether to trade
ordering for latency and memory use.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;future-directions&quot;&gt;Future Directions&lt;&#x2F;h2&gt;
&lt;p&gt;As I mentioned in the &quot;language support&quot; section of my &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;streams-concurrency&#x2F;#looking-ahead-language-support&quot;&gt;&quot;streams concurrency&quot;
post&lt;&#x2F;a&gt;,
it&#x27;d be fantastic if the Rust language itself could eventually provide
support for parallel iteration. For example writing a parallel async TCP
listener shouldn&#x27;t be more lines than writing a synchronous sequential one:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; listener = TcpListener::bind(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;span&gt;println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Listening on &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;local_addr&lt;&#x2F;span&gt;&lt;span&gt;()?);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; par stream.await? in listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;incoming&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Accepting from: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, stream.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;peer_addr&lt;&#x2F;span&gt;&lt;span&gt;()?);
&lt;&#x2F;span&gt;&lt;span&gt;    io::copy(&amp;amp;stream, &amp;amp;stream).await?;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But that&#x27;s quite a bit further out. Though now that &lt;code&gt;parallel-stream&lt;&#x2F;code&gt; exists
we can probably start prototyping what this would look like through the use
of proc macros. After all, language support for &lt;code&gt;async&#x2F;await&lt;&#x2F;code&gt; was also first
implemented &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;alexcrichton&#x2F;futures-await&quot;&gt;as a proc macro&lt;&#x2F;a&gt;.
There are some limitations around what proc macros can currently do, but I
believe the following should be feasible:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; listener = TcpListener::bind(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;span&gt;println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Listening on &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;local_addr&lt;&#x2F;span&gt;&lt;span&gt;()?);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;for_par&lt;&#x2F;span&gt;&lt;span&gt;] { stream.await? in listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;incoming&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Accepting from: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, stream.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;peer_addr&lt;&#x2F;span&gt;&lt;span&gt;()?);
&lt;&#x2F;span&gt;&lt;span&gt;    io::copy(&amp;amp;stream, &amp;amp;stream).await?;
&lt;&#x2F;span&gt;&lt;span&gt;}}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In addition to that there are quite a few more APIs to add. &lt;code&gt;parallel-stream&lt;&#x2F;code&gt;
currently only covers the basics, but we&#x27;ve setup a comprehensive list of all
methods to add in &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;async-rs&#x2F;parallel-stream&#x2F;issues&#x2F;2&quot;&gt;#2&lt;&#x2F;a&gt;.
Contributions would be most welcome!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve introduced &lt;code&gt;parallel-stream&lt;&#x2F;code&gt;, a data parallelism library
for &lt;code&gt;async-std&lt;&#x2F;code&gt;. It provides a familiar interface powering non-blocking
parallel processing of work.&lt;&#x2F;p&gt;
&lt;p&gt;Work on this library started a few months after &lt;code&gt;async-std&lt;&#x2F;code&gt; was kicked off.
However I had some trouble prototyping it, and it wasn&#x27;t until last week that
I figured out how to simplify internals enough to get it to work well.&lt;&#x2F;p&gt;
&lt;p&gt;Personally I&#x27;m happy that we&#x27;ve proven this exists, but probably don&#x27;t have
much time to maintain it going forward. If someone would like to help
maintain this and move it foward, please do get it touch!&lt;&#x2F;p&gt;
&lt;p&gt;For me it&#x27;s probably time to work on Tide again, and finish the migration to
&lt;code&gt;http-types&lt;&#x2F;code&gt;. Probably more on that in a later post. That&#x27;s all for now. Have
a good week, and stay safe!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>IO Delegation for Arc</title>
            <pubDate>Tue, 03 Mar 2020 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/io-trait-delegation-for-arc/</link>
            <guid>https://blog.yoshuawuyts.com/io-trait-delegation-for-arc/</guid>
            <description>&lt;p&gt;When &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;stjepang&quot;&gt;Stjepan&lt;&#x2F;a&gt; and I were designing async-std,
one of the core design principles was to make it resemble the standard
library as closely as possible. This meant the same names, APIs, and traits
as the standard library so that the same patterns of sync Rust could be used
in async Rust as well.&lt;&#x2F;p&gt;
&lt;p&gt;One of those patterns is perhaps lesser known but integral to std’s
functioning: &lt;code&gt;impl Read&#x2F;Write for &amp;amp;Type&lt;&#x2F;code&gt;. What this means is that if you have
a reference to an IO type, such as &lt;code&gt;File&lt;&#x2F;code&gt; or &lt;code&gt;TcpStream&lt;&#x2F;code&gt;, you’re still able
to call &lt;code&gt;Read&lt;&#x2F;code&gt; and &lt;code&gt;Write&lt;&#x2F;code&gt; methods thanks to some interior mutability tricks.&lt;&#x2F;p&gt;
&lt;p&gt;The implication of this is also that if you want to share a &lt;code&gt;std::fs::File&lt;&#x2F;code&gt;
between multiple threads you don’t need to use an expensive
&lt;code&gt;Arc&amp;lt;Mutex&amp;lt;File&amp;gt;&amp;gt;&lt;&#x2F;code&gt; because an &lt;code&gt;Arc&amp;lt;File&amp;gt;&lt;&#x2F;code&gt; suffices. And because of how we
designed &lt;code&gt;async-std&lt;&#x2F;code&gt;, this works for &lt;code&gt;async_std::fs::File&lt;&#x2F;code&gt; as well!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;For simplicity in this post we&#x27;ll be using &lt;code&gt;std::io::*&lt;&#x2F;code&gt; examples instead of
the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-io&quot;&gt;&lt;code&gt;futures-io&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; variants because they&#x27;re
shorter. But &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;rust-streams&#x2F;#streams-and-roles&quot;&gt;since async and sync IO traits are closely
related&lt;&#x2F;a&gt;,
everything in this post applies to both.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;problems-with-delegation&quot;&gt;Problems with delegation&lt;&#x2F;h2&gt;
&lt;p&gt;A simplified version of &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;async-http&#x2F;&quot;&gt;&lt;code&gt;async-h1&lt;&#x2F;code&gt;&#x27;s&lt;&#x2F;a&gt;&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-h1&#x2F;1.0.0&#x2F;async_h1&#x2F;fn.accept.html&quot;&gt;&lt;code&gt;accept&lt;&#x2F;code&gt;
function&lt;&#x2F;a&gt; has the
following bounds (simplified):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;accept&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;IO&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;url&lt;&#x2F;span&gt;&lt;span&gt;: http_types::Url, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;io&lt;&#x2F;span&gt;&lt;span&gt;: IO) -&amp;gt; http_types::Result&amp;lt;()&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    IO: AsyncRead + AsyncWrite + Clone;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Each call to &lt;code&gt;accept&lt;&#x2F;code&gt; takes a &lt;code&gt;url&lt;&#x2F;code&gt; and some IO object that implements
&lt;code&gt;Clone&lt;&#x2F;code&gt; and async versions of &lt;code&gt;Read&lt;&#x2F;code&gt; and &lt;code&gt;Write&lt;&#x2F;code&gt;. The &lt;code&gt;Clone&lt;&#x2F;code&gt; bound is
important because it enables freely copying owned handles of the same value
within the function. This was the only way to enable this API under Rust&#x27;s
current borrowing rules &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#borrowing-rules&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;borrowing-rules&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Once we get &quot;streamable streams&quot; &#x2F; &quot;non-overlapping
streams&quot; we might be able to express this without cloning at all because we
can keep references alive in more cases. But that&#x27;s not scheduled to land
anytime soon.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;You might expect that if we wrap an IO type T in an &lt;code&gt;Arc&lt;&#x2F;code&gt; that it would
implement &lt;code&gt;Clone + Read + Write&lt;&#x2F;code&gt;. But in reality it only implements &lt;code&gt;Clone + Deref&amp;lt;T&amp;gt;&lt;&#x2F;code&gt;. This means that if we want to access any of the &lt;code&gt;Read&lt;&#x2F;code&gt; or &lt;code&gt;Write&lt;&#x2F;code&gt;
functions we must first dereference it using &lt;code&gt;&amp;amp;&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; stream = TcpStream::connect(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;localhost:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; stream = Arc::new(stream);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;stream1.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello world&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; OK: Read is available for &amp;amp;Arc&amp;lt;TcpStream&amp;gt;.
&lt;&#x2F;span&gt;&lt;span&gt;stream1.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello world&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Error: Read is not available for Arc&amp;lt;TcpStream&amp;gt;.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However, there&#x27;s an escape hatch here: we can create a wrapper type around
&lt;code&gt;Arc&amp;lt;TcpStream&amp;gt;&lt;&#x2F;code&gt; that implements &lt;code&gt;Read + Write&lt;&#x2F;code&gt; by dereferencing &lt;code&gt;&amp;amp;T&lt;&#x2F;code&gt; internally:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Clone)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Stream(Arc&amp;lt;TcpStream&amp;gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Read &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Stream {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;        &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;],
&lt;&#x2F;span&gt;&lt;span&gt;    ) -&amp;gt; io::Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        (&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(buf)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Write &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Stream {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]) -&amp;gt; io::Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        (&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(buf)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;flush&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; io::Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        (&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;flush&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are a few shortcomings here though: it&#x27;s not generic over any type and
it&#x27;s yet another wrapper type around &lt;code&gt;Arc&lt;&#x2F;code&gt;. Wouldn&#x27;t it be much nicer if
&lt;code&gt;Arc&lt;&#x2F;code&gt; exposed &lt;code&gt;Read&lt;&#x2F;code&gt; and &lt;code&gt;Write&lt;&#x2F;code&gt; without the need for another wrapper type?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-better-way-forward&quot;&gt;A better way forward&lt;&#x2F;h2&gt;
&lt;p&gt;We implemented a proof of concept of conditional support for &lt;code&gt;Read&lt;&#x2F;code&gt;,
&lt;code&gt;AsyncRead&lt;&#x2F;code&gt;, &lt;code&gt;Write&lt;&#x2F;code&gt;, and &lt;code&gt;AsyncWrite&lt;&#x2F;code&gt; on &lt;code&gt;Arc&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; as the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;io-arc&quot;&gt;&lt;code&gt;io-arc&lt;&#x2F;code&gt;
crate&lt;&#x2F;a&gt;. The way it’s implemented is as follows:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; A variant of `Arc` that delegates IO traits if available on `&amp;amp;T`.
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Debug)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;IoArc&amp;lt;T&amp;gt;(Arc&amp;lt;T&amp;gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; IoArc&amp;lt;T&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Create a new instance of IoArc.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: T) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;(Arc::new(data))
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; Read &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;IoArc&amp;lt;T&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt; T: Read,
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]) -&amp;gt; io::Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        (&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(buf)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T&amp;gt; Write &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;IoArc&amp;lt;T&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt; T: Write,
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]) -&amp;gt; io::Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        (&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(buf)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;flush&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; io::Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        (&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;flush&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using higher ranked trait bounds we’re able to implement &lt;code&gt;Read&lt;&#x2F;code&gt; for &lt;code&gt;T&lt;&#x2F;code&gt; if
&lt;code&gt;&amp;amp;T: Read&lt;&#x2F;code&gt;. This removes the need entirely for intermediate structs, and
allows working directly with an &lt;code&gt;Arc&lt;&#x2F;code&gt;-like construct using any io type. This
should be possible to implement directly on &lt;code&gt;Arc&lt;&#x2F;code&gt;, which would remove the
need for wrapper types all together.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;are-there-any-alternatives&quot;&gt;Are there any alternatives?&lt;&#x2F;h2&gt;
&lt;p&gt;The way we solved this in &lt;code&gt;async-std&lt;&#x2F;code&gt; was to &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.5.0&#x2F;async_std&#x2F;net&#x2F;struct.TcpStream.html#impl-Clone&quot;&gt;implement &lt;code&gt;Clone&lt;&#x2F;code&gt; for
&lt;code&gt;TcpStream&lt;&#x2F;code&gt;
directly&lt;&#x2F;a&gt;.
This shouldn&#x27;t be a bottleneck in practice, but we haven&#x27;t done this for
other types yet such as &lt;code&gt;File&lt;&#x2F;code&gt;. And similarly: we can&#x27;t expect &lt;code&gt;std&lt;&#x2F;code&gt; to be
able to make the same tradeoffs. &lt;code&gt;Arc&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; exposing &lt;code&gt;Read + Write&lt;&#x2F;code&gt; if
available is superior in all regards.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-are-the-downsides&quot;&gt;What are the downsides?&lt;&#x2F;h2&gt;
&lt;p&gt;All of the bounds in this post are entirely conditional, don&#x27;t introduce any
extra overhead, and don&#x27;t make use of &lt;code&gt;unsafe&lt;&#x2F;code&gt; anywhere. This should make
them a fairly uncontroversial candidate for inclusion in &lt;code&gt;std&lt;&#x2F;code&gt; -- all they do
is make an existing pattern easier to use.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-next&quot;&gt;What’s next?&lt;&#x2F;h2&gt;
&lt;p&gt;It&#x27;d be great if these bounds could be made part of std. I haven&#x27;t
contributed much to &lt;code&gt;std&lt;&#x2F;code&gt; yet, and am somewhat daunted by making my first
contribution. But maybe this could be a first contribution?&lt;&#x2F;p&gt;
&lt;p&gt;If these bounds get accepted in &lt;code&gt;std&lt;&#x2F;code&gt; for the &lt;code&gt;std::io&lt;&#x2F;code&gt; traits, they&#x27;d
make an excellent addition for the &lt;code&gt;futures::io&lt;&#x2F;code&gt; traits as well. And finally
it&#x27;d be great if we could support &lt;code&gt;BufRead&lt;&#x2F;code&gt; and &lt;code&gt;AsyncBufRead&lt;&#x2F;code&gt;. There&#x27;s an
open issue for it &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yoshuawuyts&#x2F;io-arc&#x2F;issues&#x2F;1&quot;&gt;on the
repo&lt;&#x2F;a&gt;, but we haven&#x27;t quite
figured it out yet.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we’ve shown how Arc interacts with &lt;code&gt;&amp;amp;T: Read + Write&lt;&#x2F;code&gt; today, and
explained existing ways of working around its shortcomings. We’ve introduced
a novel approach to work around this and published
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;io-arc&quot;&gt;&lt;code&gt;io-arc&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; as a proof of concept how these bounds
could be implemented as part of std.&lt;&#x2F;p&gt;
&lt;p&gt;All in all this seems like exactly the kind of quality of life improvement
that would make people&#x27;s lives easier. The trait bounds for conditional
detection of &lt;code&gt;&amp;amp;T: Read &#x2F; Write&lt;&#x2F;code&gt; were incredibly tricky to write, but the
resulting usage is quite straight forward!&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;llogiq&quot;&gt;llogiq&lt;&#x2F;a&gt; for helping with the post and
the library. And &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;stjepang&quot;&gt;stjepang&lt;&#x2F;a&gt; for helping with
the post, and coming up with most of the ideas shared here.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Async HTTP</title>
            <pubDate>Tue, 25 Feb 2020 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/async-http/</link>
            <guid>https://blog.yoshuawuyts.com/async-http/</guid>
            <description>&lt;p&gt;Today &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;dignifiedquire&#x2F;&quot;&gt;Friedel Ziegelmayer&lt;&#x2F;a&gt; (Protocol
Labs), &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;ryan_levick&#x2F;&quot;&gt;Ryan Levick&lt;&#x2F;a&gt; (Microsoft)
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#employers&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, and myself would like to introduce a new set of HTTP libraries
to make writing encrypted, async http&#x2F;1.1 servers and clients easy and quick:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-h1&quot;&gt;&lt;code&gt;async-h1&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; – A streaming HTTP&#x2F;1.1 client and
server protocol implementation.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;http-types&quot;&gt;&lt;code&gt;http-types&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; – Reusable http types extracted
from the HTTP server and client frameworks: &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tide&quot;&gt;Tide&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;surf&quot;&gt;Surf&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-native-tls&quot;&gt;&lt;code&gt;async-native-tls&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; – A streaming TLS
client and server implementation &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#tls&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;employers&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;None of these projects are official projects by any one
company.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;tls&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;This library builds on the excellent work done in
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;native-tls&quot;&gt;&lt;code&gt;native-tls&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;With these libraries writing a streaming, encrypted HTTP client takes about
15 lines of code &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#10-lines&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;10-lines&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;The TCP stream, HTTP stream, and TLS stream each expect a
different subset of a URL. Most of the logic in this example is about
constructing the right argument for each stream. We have &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;async-email&#x2F;async-native-tls&#x2F;issues&#x2F;15&quot;&gt;an open
issue&lt;&#x2F;a&gt; that if
implemented should make this even easier.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::io::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::net::TcpStream;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;http_types::{Method, Request, Url};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;async_std&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; http_types::Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; open a tcp connection to a host
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; stream = TcpStream::connect(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; peer_addr = stream.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;peer_addr&lt;&#x2F;span&gt;&lt;span&gt;()?;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; create a request
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; url = Url::parse(&amp;amp;format!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;https:&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;foo&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, peer_addr))?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; req = Request::new(Method::Get, url);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; encrypt the tls connection
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; host = req.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;url&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;host_str&lt;&#x2F;span&gt;&lt;span&gt;()?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; stream = async_native_tls::connect(host, stream).await?;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; send the request over the encrypted connection
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = async_h1::connect(stream, req).await?;
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, res);
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And an async HTTP server is done in less than 30 lines, with much of the code
being imports, &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;streams-concurrency&#x2F;#looking-ahead-language-support&quot;&gt;async
loops&lt;&#x2F;a&gt;,
print statements, and constructing the right URL parameters:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::net::{TcpStream, TcpListener};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::task;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;http_types::{Response, StatusCode};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;async_std&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; http_types::Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Open up a TCP connection and create a URL.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; listener = TcpListener::bind((&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;8080&lt;&#x2F;span&gt;&lt;span&gt;)).await?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; addr = format!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;http:&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;local_addr&lt;&#x2F;span&gt;&lt;span&gt;()?);
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;listening on &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, addr);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; For each incoming TCP connection, spawn a task and call `accept`.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; incoming = listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;incoming&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(stream) = incoming.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().await {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; stream = stream?;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; addr = addr.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        task::spawn(async {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span&gt;Err(err) = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;accept&lt;&#x2F;span&gt;&lt;span&gt;(addr, stream).await {
&lt;&#x2F;span&gt;&lt;span&gt;                eprintln!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, err);
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        });
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Take a TCP stream, and convert it into sequential HTTP request &#x2F; response pairs.
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;accept&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;addr&lt;&#x2F;span&gt;&lt;span&gt;: String, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;stream&lt;&#x2F;span&gt;&lt;span&gt;: TcpStream) -&amp;gt; http_types::Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;starting new connection from &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, stream.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;peer_addr&lt;&#x2F;span&gt;&lt;span&gt;()?);
&lt;&#x2F;span&gt;&lt;span&gt;    async_h1::accept(&amp;amp;addr, stream.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;(), |&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;_req&lt;&#x2F;span&gt;&lt;span&gt;| async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; res = Response::new(StatusCode::Ok);
&lt;&#x2F;span&gt;&lt;span&gt;        res.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert_header&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Content-Type&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;text&#x2F;plain&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span&gt;        res.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;set_body&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;        Ok(res)
&lt;&#x2F;span&gt;&lt;span&gt;    })
&lt;&#x2F;span&gt;&lt;span&gt;    .await?;
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Creating an encrypted version of this would be only a few extra lines: load a
certificate, and wrap the &lt;code&gt;accept&lt;&#x2F;code&gt; stream:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::net::TcpListener;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::fs::File;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; key = File::open(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;identity.pfx&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; pass = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&amp;lt;password&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; listener = TcpListener::bind(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(stream, _) = listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;accept&lt;&#x2F;span&gt;&lt;span&gt;().await?;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; stream = async_native_tls::accept(key, pass, stream).await?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Continue handling the stream here
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;streams&quot;&gt;Streams&lt;&#x2F;h2&gt;
&lt;p&gt;As you may have noticed, the libraries we&#x27;ve written are centered around
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;rust-streams&#x2F;&quot;&gt;streams&lt;&#x2F;a&gt;. This is because
streams in Rust provide an incredible degree of &lt;em&gt;composability&lt;&#x2F;em&gt;.
For example, using surf to copy the body an HTTP request to a file is a
combination of &quot;make an HTTP request&quot;, and &quot;copy to a file&quot;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; req = surf::get(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;https:&#x2F;&#x2F;example.com&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;span&gt;io::copy(req, File::open(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;example.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)).await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With &lt;code&gt;async-h1&lt;&#x2F;code&gt; and &lt;code&gt;async-native-tls&lt;&#x2F;code&gt; we wanted to not only make this
possible at the framework layer; we wanted this to extend to the protocol
layer as well. Because we believe that if it becomes easier to combine parts
of a stack, it becomes easier for the ecosystem to make progress on the stack
as a whole.&lt;&#x2F;p&gt;
&lt;p&gt;Putting it concretely, if you want to run &lt;code&gt;async-h1&lt;&#x2F;code&gt; over a
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.5.0&#x2F;async_std&#x2F;os&#x2F;unix&#x2F;net&#x2F;struct.UnixStream.html&quot;&gt;&lt;code&gt;UnixStream&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
to say, communicate with &lt;a href=&quot;https:&#x2F;&#x2F;docs.docker.com&#x2F;engine&#x2F;api&#x2F;v1.27&quot;&gt;a local
daemon&lt;&#x2F;a&gt;, all you have to do is
replace the &lt;code&gt;TcpStream&lt;&#x2F;code&gt; with a &lt;code&gt;UnixStream&lt;&#x2F;code&gt; and you&#x27;re good to go. There&#x27;s no
need to start from scratch or fork existing projects.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;shared-abstractions&quot;&gt;Shared abstractions&lt;&#x2F;h2&gt;
&lt;p&gt;As we mentioned at the start: the &lt;code&gt;http-types&lt;&#x2F;code&gt; crate has been extracted from
the Tide and Surf frameworks. Prior to this we were using the
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hyperium&#x2F;http&quot;&gt;&lt;code&gt;hyperium&#x2F;http&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate, which provides
abstractions for several HTTP idioms, but for example doesn&#x27;t provide an HTTP
body, cookies, mime types, and doesn&#x27;t implement &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;url&#x2F;2.1.1&#x2F;url&#x2F;&quot;&gt;the url
standard&lt;&#x2F;a&gt;. These are all fine choices with
distinct tradeoffs. But &lt;em&gt;for us&lt;&#x2F;em&gt; we were finding that we had a lot of
duplicate code between Tide and Surf, which was becoming a maintenance
burden &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#splitting-the-ecosystem&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;splitting-the-ecosystem&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;If the past is any indication, it&#x27;s likely
someone will bring up the &lt;em&gt;&quot;You&#x27;re splitting the ecosystem&quot;&lt;&#x2F;em&gt; meme when
discussing this post. This is an argument to authority: rather than explore
how things could be improved, we should relinquish to the status quo. But
this conveniently fails to acknowledge that writing and sharing code in the
public domain &lt;em&gt;is&lt;&#x2F;em&gt; collaboration. Our ideas are now available to try out and
improve upon with no restrictions other than attribution. Sharing findings in
the public domain is not a divisive act. Fanning controversy using &lt;em&gt;&quot;us vs
them&quot;&lt;&#x2F;em&gt; rhetoric however, is.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;So instead we&#x27;ve opted to create &lt;code&gt;http-types&lt;&#x2F;code&gt;, a shared abstraction that
covers the full range of HTTP idioms, and provides a
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-io&#x2F;0.3.4&#x2F;futures_io&#x2F;trait.AsyncBufRead.html&quot;&gt;streaming&lt;&#x2F;a&gt;
body. We&#x27;ve found that this has made it easier to create a rich set of HTTP
abstractions for us, to the point where we suspect both Tide and Surf&#x27;s types
will be minimal wrappers around &lt;code&gt;http-types&lt;&#x2F;code&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;http-service&quot;&gt;&lt;code&gt;http-service&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;http-client&quot;&gt;&lt;code&gt;http-client&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; respectively. Only bringing in framework-specific additions
such as middleware and routing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;error-handling&quot;&gt;Error Handling&lt;&#x2F;h2&gt;
&lt;p&gt;Additionally &lt;code&gt;http-types&lt;&#x2F;code&gt; provides a status-code aware &lt;code&gt;Error&lt;&#x2F;code&gt; type, making
it possible to associate status codes with errors. This work leans heavily on
David Tolnay&#x27;s excellent work on &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;anyhow&#x2F;&quot;&gt;&lt;code&gt;anyhow&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Under the hood &lt;code&gt;http_types::Error&lt;&#x2F;code&gt; is a combination of a boxed error&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;status code. Just like &lt;code&gt;anyhow&lt;&#x2F;code&gt;, any error can be cast to this type using
the &lt;code&gt;?&lt;&#x2F;code&gt; operator.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Additionally we also provide a &lt;code&gt;ResultExt&lt;&#x2F;code&gt; trait that exposes a &lt;code&gt;status&lt;&#x2F;code&gt;
method on &lt;code&gt;Result&lt;&#x2F;code&gt; that serves as a shorthand to cast to this type. This is
useful to quickly assign status codes to existing errors &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#default-status&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;default-status&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;By default casting from a boxed error to
&lt;code&gt;http_types::Error&lt;&#x2F;code&gt; will assume it&#x27;s a &lt;code&gt;500: Internal Server Error&lt;&#x2F;code&gt;. The
&lt;code&gt;.status&lt;&#x2F;code&gt; method is mostly useful for assigning other status codes.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Get the length of a file in bytes.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Converts an `io::Error` to `http_types::Error`.
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;file_length&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;: Path) -&amp;gt; http_types::Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = fs::read(p).await.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;status&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;501&lt;&#x2F;span&gt;&lt;span&gt;)?;
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(b.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a first step for us to make error handling a first-class citizen in
HTTP frameworks such as Tide and Surf. We&#x27;re still exploring how the general
pattern feels, and would love to hear your thoughts!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;trait-forwarding&quot;&gt;Trait forwarding&lt;&#x2F;h2&gt;
&lt;p&gt;But we&#x27;re not using &lt;code&gt;AsRef&lt;&#x2F;code&gt; exclusively for error handling; we use it
extensively throughout our libraries. This has been inspired by rustwasm&#x27;s
approach to events in &lt;code&gt;web-sys&lt;&#x2F;code&gt;. Rather than define a new trait that&#x27;s shared
by objects, each DOM object implements
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;web-sys&#x2F;0.3.35&#x2F;web_sys&#x2F;struct.EventTarget.html#impl-AsRef%3CEventTarget%3E&quot;&gt;&lt;code&gt;AsRef&amp;lt;EventTarget&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;,
allowing it to be referenced as an &lt;code&gt;EventTarget&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In &lt;code&gt;http-types&lt;&#x2F;code&gt;, we implement
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nightly&#x2F;std&#x2F;convert&#x2F;trait.AsRef.html&quot;&gt;&lt;code&gt;AsRef&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nightly&#x2F;std&#x2F;convert&#x2F;trait.AsMut.html&quot;&gt;&lt;code&gt;AsMut&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to
convert between various types. For example a &lt;code&gt;Request&lt;&#x2F;code&gt; is a combination of a
byte stream, headers, and a URL. So it implements &lt;code&gt;AsRef&amp;lt;Url&amp;gt;&lt;&#x2F;code&gt;,
&lt;code&gt;AsRef&amp;lt;Headers&amp;gt;&lt;&#x2F;code&gt;, and &lt;code&gt;AsyncRead&lt;&#x2F;code&gt;. Similarly a &lt;code&gt;Response&lt;&#x2F;code&gt; is a combination of
a byte stream, headers, and a status code. So it implements
&lt;code&gt;AsRef&amp;lt;StatusCode&amp;gt;&lt;&#x2F;code&gt;, &lt;code&gt;AsRef&amp;lt;Headers&amp;gt;&lt;&#x2F;code&gt;, and &lt;code&gt;AsyncRead&lt;&#x2F;code&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#interface&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;interface&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;Before adopting this pattern we played around for a bit with
defining custom traits, or following the pattern of exposing &lt;code&gt;headers&lt;&#x2F;code&gt; &#x2F;
&lt;code&gt;headers_mut&lt;&#x2F;code&gt; in the interface. All of these felt rather awkward, and it was
only after playing around with
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;os&#x2F;unix&#x2F;io&#x2F;trait.AsRawFd.html&quot;&gt;&lt;code&gt;AsRawFd&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; more
that we realized &lt;code&gt;AsRef&lt;&#x2F;code&gt; was the perfect fit here. And seeing it used in
practice in the &lt;code&gt;web-sys&lt;&#x2F;code&gt; crates solidified that intuition further.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This pattern is repeated throughout our crates. Worth noting is that we don&#x27;t
allow creating &lt;code&gt;Headers&lt;&#x2F;code&gt; as a standalone type, yet it still serves as a
shared interface between &lt;code&gt;Request&lt;&#x2F;code&gt;, &lt;code&gt;Response&lt;&#x2F;code&gt;, and &lt;code&gt;Trailers&lt;&#x2F;code&gt;. That means
that if you want to read or write to any of these types you can do:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;set_cors&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;headers&lt;&#x2F;span&gt;&lt;span&gt;: impl AsMut&amp;lt;http_types::Headers&amp;gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; set cors headers here
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;forwarded_for&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;headers&lt;&#x2F;span&gt;&lt;span&gt;: impl AsRef&amp;lt;http_types::Headers&amp;gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; get the X-forwarded-for header
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And this code will happily take a &lt;code&gt;Request&lt;&#x2F;code&gt;, &lt;code&gt;Response&lt;&#x2F;code&gt;, or &lt;code&gt;Trailers&lt;&#x2F;code&gt; and
perform the actions without a problem:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; fwd1 = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;forwarded_for&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;req);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; fwd2 = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;forwarded_for&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;res);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; fwd3 = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;forwarded_for&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;trailers);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The plan is for Tide and Surf&#x27;s &lt;code&gt;Request&lt;&#x2F;code&gt; and &lt;code&gt;Response&lt;&#x2F;code&gt; pairs to also
forward the same types. So whether you work with &lt;code&gt;http-types&lt;&#x2F;code&gt; directly, or
targeting one of the frameworks the code you write to interface with them
remains the same.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;compatibility&quot;&gt;Compatibility&lt;&#x2F;h2&gt;
&lt;p&gt;Something else that we&#x27;re excited about is the level of &lt;em&gt;compatibility&lt;&#x2F;em&gt; that
we have with this new stack. It&#x27;s now possible to &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;http-service-lambda&quot;&gt;run servers as Lambda functions&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;http-client&#x2F;1.1.1&#x2F;http_client&#x2F;native&#x2F;index.html&quot;&gt;HTTP clients in the browser&lt;&#x2F;a&gt;, and whichever combination of Rust server, TLS,
DNS, and transport you want.&lt;&#x2F;p&gt;
&lt;p&gt;In order for &lt;code&gt;http-types&lt;&#x2F;code&gt; to work with crates in the ecosystem that use
&lt;code&gt;hyperium&#x2F;http&lt;&#x2F;code&gt;, we provide &lt;code&gt;From&lt;&#x2F;code&gt; and &lt;code&gt;Into&lt;&#x2F;code&gt; implementations for all our
types that can be enabled through a feature flag:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-toml &quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span&gt;[dependencies]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;http-types &lt;&#x2F;span&gt;&lt;span&gt;= { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;version &lt;&#x2F;span&gt;&lt;span&gt;= &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;features &lt;&#x2F;span&gt;&lt;span&gt;= [&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hyperium_http&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;] }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Because &lt;code&gt;hyperium&#x2F;http&lt;&#x2F;code&gt; doesn&#x27;t provide a body implementation, compatibility
won&#x27;t always be frictionless. But this is as close as we could get it, and
should cover many cases &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#isahc&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;!&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;isahc&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;For us one of the most important cases to target is compatibility
with &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;isahc&quot;&gt;isahc&lt;&#x2F;a&gt;, an async HTTP library backed by curl.
Because it also uses &lt;code&gt;AsyncRead&lt;&#x2F;code&gt; as its body, the compat layer makes working
with it really nice.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This means that between &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;http-client&quot;&gt;&lt;code&gt;http-client&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;http-service&quot;&gt;&lt;code&gt;http-service&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, and &lt;code&gt;http-types&lt;&#x2F;code&gt; we provide
an incredibly flexible layer that&#x27;s widely compatible.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;design-philosophy&quot;&gt;Design philosophy&lt;&#x2F;h2&gt;
&lt;p&gt;Most of the work on these projects has been driven by curiosity. Trying to
answer questions such as: &quot;What does an HTTP library look like if it&#x27;s
designed for async Rust? Are generics required to allow TCP and TLS to be
configured? Can HTTP&#x2F;1.1 be expressed as streams?&quot;&lt;&#x2F;p&gt;
&lt;p&gt;What we&#x27;ve tried to build is a set of libraries that will lower the barrier
to experimenting with async HTTP in Rust. We use few new traits, limit the
amount of generics we provide, compile incredibly fast, and closely follow
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;1.0.0&#x2F;style&#x2F;style&#x2F;naming&#x2F;README.html&quot;&gt;Rust&#x27;s naming
conventions&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We feel the end-result is a set of libraries that are easy to pick up, easy
to hack on, and easy to maintain. &lt;code&gt;async-h1&lt;&#x2F;code&gt;&#x27;s implementation is
only a few hundred lines for the client and server each. Which means if you
ever hit a bug or want to make a change, it&#x27;s possible to make the changes
without relying on resident experts. We hope this will empower people to try
things out, and continue to improve beyond where we&#x27;ve gone.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;acknowledgements&quot;&gt;Acknowledgements&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;d like to take a moment to appreciate and thank the
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hyperium&quot;&gt;Hyperium&lt;&#x2F;a&gt; team for all the work they&#x27;ve
done. While we have concrete reasons to embark on a different path than the
one they&#x27;re on, the reality is that this has only been possible because of
the work they&#x27;ve done.&lt;&#x2F;p&gt;
&lt;p&gt;To name examples: &lt;code&gt;async-h1&lt;&#x2F;code&gt; makes use of the excellent
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;httparse&#x2F;&quot;&gt;&lt;code&gt;httparse&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; library. And
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;http&quot;&gt;&lt;code&gt;hyperium&#x2F;http&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; has long been a center component of
Tide and Surf, and was the standard which we measured our work on
&lt;code&gt;http-types&lt;&#x2F;code&gt; against.&lt;&#x2F;p&gt;
&lt;p&gt;Even though the purpose of this post is to showcase the innovations we&#x27;re
introducing to HTTP in Rust, it&#x27;s worth acknowledging that our groups have
more in common than might first appear. We all want HTTP in Rust to succeed.
We care about usability. We care about performance. The difference lies in
how to achieve achieve those goals.&lt;&#x2F;p&gt;
&lt;p&gt;In the spirit of healthy competition, we think it&#x27;s worth taking a moment to
acknowledge our colleagues on the other side, and appreciate the work that
they&#x27;ve done. Because we couldn&#x27;t have done this without them. Thanks!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-next&quot;&gt;What&#x27;s next?&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;d love for you to get involved! Come hang out with us on
&lt;a href=&quot;https:&#x2F;&#x2F;discord.gg&#x2F;x2gKzst&quot;&gt;Discord&lt;&#x2F;a&gt;, or consider helping out with
documentation, tests, or issues &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;http-rs&quot;&gt;on GitHub&lt;&#x2F;a&gt;. Our
main goals right now are to improve test coverage, iron out the bumps based
on user feedback, and improve protocol support &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#protocol-support&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ve talked about authoring an &lt;code&gt;async-h2&lt;&#x2F;code&gt; crate, but we currently don&#x27;t have
the bandwidth to. We&#x27;d like to see Tide ship a 1.0 eventually, and continue
to improve protocol support and ergonomics to make Rust&#x27;s HTTP stack not just
one of the fastest, but also the easiest to use of all languages.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve introduced three new HTTP libraries: &lt;code&gt;async-h1&lt;&#x2F;code&gt;,
&lt;code&gt;async-native-tls&lt;&#x2F;code&gt;, and &lt;code&gt;http-types&lt;&#x2F;code&gt;. These libraries have been built
natively for async byte streams, and provide a carefully balanced API that
combines ergonomics with performance.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s hard to capture all the details that have gone into these libraries.
Over the past 6 months we&#x27;ve been writing and rewriting these libraries over
and over. We feel proud to be able to share them with you, and think it
provides an exciting direction for HTTP in Rust.&lt;&#x2F;p&gt;
&lt;p&gt;We hope you&#x27;ll enjoy the work we&#x27;ve shared today, and we&#x27;re excited for you
to try it out!&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;protocol-support&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;&#x2F;sup&gt;
&lt;p&gt;For &lt;code&gt;async-h1&lt;&#x2F;code&gt; we&#x27;re missing chunked encoding for client
streams. For &lt;code&gt;async-native-tls&lt;&#x2F;code&gt; TLS 1.3 is not there yet. And &lt;code&gt;http-types&lt;&#x2F;code&gt;
doesn&#x27;t have structured constructors for all headers yet.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;Thanks to Joshua Gould and Florian Gilcher for providing feedback on this
post. Tirr-c for helping out with the libraries. And Stjepan Glavina for
helping debug some of the worst trait bound problems imaginable.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Tide Channels</title>
            <pubDate>Wed, 29 Jan 2020 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/tide-channels/</link>
            <guid>https://blog.yoshuawuyts.com/tide-channels/</guid>
            <description>&lt;p&gt;WebSocket (WS) support for &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;http-rs&#x2F;tide&quot;&gt;Tide&lt;&#x2F;a&gt; has been
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;http-rs&#x2F;tide&#x2F;issues&#x2F;67&quot;&gt;a long-anticipated feature&lt;&#x2F;a&gt;. More
recently &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;http-rs&#x2F;tide&#x2F;issues&#x2F;234&quot;&gt;requests for Server Sent Events (SSE)
support&lt;&#x2F;a&gt; have started to pop up
as well. In this post we&#x27;ll look at the motivation, requirements, and design
for WS and SSE support in Tide. But to not keep you waiting, this is the Tl;Dr
of what we&#x27;ve come up with:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; app = tide::new();
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;sse&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(tide::sse()); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Endpoint to connect new SSE channels on.
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(async |req| {
&lt;&#x2F;span&gt;&lt;span&gt;    req.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;sse&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello Chashu&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Send a message over the SSE channel.
&lt;&#x2F;span&gt;&lt;span&gt;    Response::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;listen&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;Note: unlike some of my other posts that document work that&#x27;s been completed
already, this post documents designs that are currently underway. The upside
of this is that I can share my notes as I&#x27;m doing research! The downside is
that the designs outlined here don&#x27;t exist yet, and will likely change during
implementation and stabilization.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-channels&quot;&gt;Why channels?&lt;&#x2F;h2&gt;
&lt;p&gt;Before diving into &lt;em&gt;how&lt;&#x2F;em&gt; WS and SSE support could be exposed it&#x27;s worth
asking &lt;em&gt;why&lt;&#x2F;em&gt; we want these features in the first place. Live chat is a pretty
common example, but however fun that is to write, most uses are more boring.
Examples include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;When a new notification is available, update the notification count.&lt;&#x2F;li&gt;
&lt;li&gt;When a new email is available, fetch it into the inbox.&lt;&#x2F;li&gt;
&lt;li&gt;When kicking off a CI process, push the terminal output into the browser.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;These features could all be implemented by periodically making HTTP requests
to the server to check whether new data is available. But instead using WS or
SSE streams allows that data to be sent to the client as soon as the data is
available. This often results in this information being presented sooner in
browsers, which often &lt;em&gt;feels&lt;&#x2F;em&gt; good &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#performance&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;performance&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;It&#x27;s hard to definitively say whether WS&#x2F;SSE performs better
than repeatedly polling. With HTTP&#x2F;1.1 it probably is. But with
HTTP&#x2F;2.0 many of the downsides of making repeated requests are gone, and
keeping a separate WS connection open might in fact be slower. But work is
being done on &lt;a href=&quot;https:&#x2F;&#x2F;tools.ietf.org&#x2F;html&#x2F;rfc8441&quot;&gt;enabling WS support over
HTTP&#x2F;2.0&lt;&#x2F;a&gt; so it&#x27;s hard to make any
definitive statements about performance. It all depends.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;I think the best way to think about WS and SSE is as networked
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;sync&#x2F;mpsc&#x2F;fn.channel.html&quot;&gt;channels&lt;&#x2F;a&gt;. Messages
are sent by one side and received by the other. SSE provides unidirectional
channels. WS provides bidirectional channels (both sides of the channel can
send messages to the other side). As we&#x27;ll see later on, features such as
broadcasting and multi-producer support can be enabled for either channel
kind.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;which-apis-do-we-need&quot;&gt;Which APIs do we need?&lt;&#x2F;h2&gt;
&lt;p&gt;Implementations for async SSE and WS streams already exist on crates.io.
Examples include
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sdroege&#x2F;async-tungstenite&quot;&gt;&lt;code&gt;async-tungstenite&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;goto-bus-stop&#x2F;sse-codec&quot;&gt;&lt;code&gt;sse-codec&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. But while these
are great building blocks to build upon, exposing them from Tide without
analyzing how people would want to use them would result in a poor end-user
experience &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#checklists&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#over-abstraction&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;checklists&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Many frameworks (of any kind) feel like they were designed by
walking down a checklist of features. On paper these frameworks are great
because they tick all boxes and infinitely flexible. But in their flexibility
they fail to provide meaningful abstractions, shifting the burden of using
APIs correctly onto the user. This rarely leads to pleasant user experiences.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;over-abstraction&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;While talking about abstractions: finding the right layer
to abstract on is a tedious process. Abstract too much, and unexpected uses
that should be valid become impossible. Abstract too little, and APIs become
hard to use and prone to error. The task of API design is to find the
middle ground, and balance that with other forces such as consistency and
performance. And getting things right takes &lt;em&gt;time&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Channel implementations for HTTP servers can roughly be split up into two
categories &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#categories&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sending messages from &lt;em&gt;inside&lt;&#x2F;em&gt; HTTP endpoints.&lt;&#x2F;strong&gt; For example: a file upload
is triggered, and we want to send progress events back to the client
while we process it.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Sending messages from &lt;em&gt;outside&lt;&#x2F;em&gt; HTTP endpoints.&lt;&#x2F;strong&gt; For example: our email
service creates a &lt;a href=&quot;https:&#x2F;&#x2F;www.rabbitmq.com&#x2F;&quot;&gt;RabbitMQ&lt;&#x2F;a&gt; event, which is
picked up by our server, and notifies a connected client.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;categories&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;I initially missed the distinction here, but Julian Gruber
&lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;juliangruber&#x2F;status&#x2F;1222084350692548609&quot;&gt;pointed out on
Twitter&lt;&#x2F;a&gt; that we
did in fact need something like this.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This calls for the introduction of two-ish APIs: one for sending messages
from inside HTTP endpoints, and one for sending messages outside of it. And
in turn there should be variants for both SSE and WS.&lt;&#x2F;p&gt;
&lt;p&gt;Another consideration is that there should be a mechanism to easily access
channels associated with the same peer. But it should also be possible to
access channels associated with other peers.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;channel-states&quot;&gt;Channel states&lt;&#x2F;h3&gt;
&lt;p&gt;In theory any channel can exist in one of 3 states:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;connected&lt;&#x2F;li&gt;
&lt;li&gt;not connected, but will connect&lt;&#x2F;li&gt;
&lt;li&gt;will definitely not connect&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;However we can&#x27;t make any meaningful distinction at the framework layer
between &quot;currently not connected&quot;, and &quot;will never connect&quot; because we can&#x27;t
know for sure whether we&#x27;ve encountered a race condition, or if this is
intended behavior. &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#app-states&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The way to provide stricter guarantees around Tide&#x27;s APIs is for application
authors to encode stricter guarantees for their applications by writing
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tide&#x2F;0.5.1&#x2F;tide&#x2F;#extension-traits&quot;&gt;Extension Traits&lt;&#x2F;a&gt;. This
is part of Tide&#x27;s layered design.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;app-states&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;If an API is public clients may or may not provide websocket
support as well. This is different from applications where the author
controls both client and server impls, where that guarantee &lt;em&gt;can&lt;&#x2F;em&gt; be made.
Tide needs to support both, so we can&#x27;t codify any assumptions about what it
means when a client isn&#x27;t connected.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;api-design&quot;&gt;API design&lt;&#x2F;h2&gt;
&lt;p&gt;The design we&#x27;re going for in Tide is to have a managed pool of client
connections inside the framework, and expose convenience methods to access
them from endpoints and on registration.&lt;&#x2F;p&gt;
&lt;p&gt;Channels will be subdivided under two flavors: Server Sent Events (SSE), and
WebSockets (WS). Their APIs will be most mostly similar, with the main
difference being that WS channels can receive messages and implement
&lt;code&gt;Stream&amp;lt;Item = Message&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;registering-a-new-channel&quot;&gt;Registering a new channel&lt;&#x2F;h3&gt;
&lt;p&gt;Establishing a new channel is similar for both SSE and WS:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; app = tide::new();
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;sse&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(tide::sse());
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;ws&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(tide::ws());
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In the case of WS an HTTP upgrade is performed, which has a handshake
procedure and some other details. While in the SSE case a response is
instantiated by sending the right response headers, and then keeping the body
stream open.&lt;&#x2F;p&gt;
&lt;p&gt;In addition to shorthand functions, we should also allow configuration of
both channel kinds. By default the shorthand function would provide things
like timeouts, keepalive messages, and other values. But these should all be
configurable through the constructors.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; app tide::new();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; ws = tide::ws().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;timeout&lt;&#x2F;span&gt;&lt;span&gt;(Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;ws&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(ws);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;registering-external-channel-handlers&quot;&gt;Registering external channel handlers&lt;&#x2F;h3&gt;
&lt;p&gt;Similar to &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.4.0&#x2F;async_std&#x2F;sync&#x2F;fn.channel.html&quot;&gt;async-std&#x27;s
channels&lt;&#x2F;a&gt;,
Tide&#x27;s channels would be cloned so each request can get their own
copy and we don&#x27;t ever have to worry about lifetimes.&lt;&#x2F;p&gt;
&lt;p&gt;On creation the channel structs should provide hooks so that when a new
channel is instantiated, a callback is called providing the channel itself.
Probably for good measure it&#x27;d also be useful to provide a copy of
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tide&#x2F;0.5.1&#x2F;tide&#x2F;#state&quot;&gt;&lt;code&gt;State&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; app tide::new();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; ws = tide::ws_with(async |ws: WebSocket, _state| {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;new websocket created&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;ws&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(ws);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The purpose of this API is to integrate with external resources that might
want to send messages to peers outside of regular the scope of an HTTP
request.&lt;&#x2F;p&gt;
&lt;p&gt;An open question here remains how to expose further metadata. Perhaps the
&lt;code&gt;WebSocket&lt;&#x2F;code&gt; struct should hold information such as &lt;code&gt;peer_addr&lt;&#x2F;code&gt;, but that&#x27;s
still unclear.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;using-channels-inside-endpoints&quot;&gt;Using channels inside endpoints&lt;&#x2F;h3&gt;
&lt;p&gt;Using channels inside endpoints should have a convenient API. Both
&lt;code&gt;req.sse()&lt;&#x2F;code&gt; and &lt;code&gt;req.ws()&lt;&#x2F;code&gt; would always return a valid channel instance
associated with the current client address.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; app = tide::new();
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;ws&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(tide::ws()); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; endpoint to establish a websocket connection on
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(async |req| {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; socket = req.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;ws&lt;&#x2F;span&gt;&lt;span&gt;(); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; access the socket
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    socket.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello chashu&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; send a message
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; msg = socket.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;recv&lt;&#x2F;span&gt;&lt;span&gt;().await?;         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; receive a message
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;message received: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, msg);  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; print a message
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    Response::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;listen&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Connectivity states can be checked through the &lt;code&gt;is_open&lt;&#x2F;code&gt; method. (See
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;tide-channels&#x2F;#channel-states&quot;&gt;Channel States&lt;&#x2F;a&gt; for more on this). Say we don&#x27;t want to
send a message unless we have an SSE connection, we could express it as
follows:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; app = tide::new();
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;sse&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(tide::sse());
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(async |req| {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; sse = req.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;sse&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; sse.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_open&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;        sse.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello Nori&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    Response::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;listen&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Support for accessing channels associated with other peers would not be
possible in the first iteration for these APIs. See &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;tide-channels&#x2F;#group-support&quot;&gt;group
support&lt;&#x2F;a&gt; for future directions we&#x27;re exploring.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;matching-channels-with-remote-peers&quot;&gt;Matching channels with remote peers&lt;&#x2F;h3&gt;
&lt;p&gt;Something to keep in mind is that we can&#x27;t match remote peers with channels
purely on incoming TCP request addresses since those could be routed by a
proxy. Instead we should be aware of &lt;code&gt;x-forwarded-for&lt;&#x2F;code&gt; and &lt;code&gt;forwarded&lt;&#x2F;code&gt;
headers.&lt;&#x2F;p&gt;
&lt;p&gt;It seems likely there is a set of APIs here that we need to define that
exposes the &quot;actual IP address&quot; of the remote peers. Any bugs around this
logic seem like they&#x27;d be a typical case of: &quot;worked on my machine, but broke
once in production because of proxies&quot; so we should put some effort in to get
this right.&lt;&#x2F;p&gt;
&lt;p&gt;Internally to the framework we should keep a hashmap that matches remote
peers with channels, and shares the right channel with the provided
&lt;code&gt;Request&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;update(2020&#x2F;01&#x2F;30):&lt;&#x2F;em&gt; as was &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;redtwitdown&#x2F;status&#x2F;1222616644452675584&quot;&gt;pointed out on
twitter&lt;&#x2F;a&gt;, in
order to safely associate peers with channels we need to introduce a session
mechanism first. Matching by IP or other params has dire security
implications.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;disconnects&quot;&gt;Disconnects&lt;&#x2F;h3&gt;
&lt;p&gt;Another topic to consider are disconnects, and retries. Both SSE and WS
handle disconnects and retries differently, but the gist is that on
disconnect we we should assume that the client might reconnect for a given
duration. And once that is over all pending channels should fail with an
&lt;code&gt;io::Error&lt;&#x2F;code&gt; (since the remote is gone).&lt;&#x2F;p&gt;
&lt;p&gt;While the channel is awaiting reconnection, the &lt;code&gt;is_open&lt;&#x2F;code&gt; method should
continue to return &lt;code&gt;true&lt;&#x2F;code&gt;. However the senders will remain waiting and might
eventually end. This is acceptable behavior since if an SSE connection
dropped midway through a session, the client itself likely dropped as well,
at which point it seems acceptable to return an error from the endpoint.&lt;&#x2F;p&gt;
&lt;p&gt;If this proves to be insufficient, we may consider extending Tide&#x27;s channel
APIs. There&#x27;s a fair chance this might be the case, so it&#x27;s something to keep
in mind.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;heartbeat&quot;&gt;Heartbeat&lt;&#x2F;h3&gt;
&lt;p&gt;In order for channels to keep their respective connections open, they need to
regularly send data over the TCP connection. Failure to do so usually results
in the underlying operating system closing a connection and returning a
timeout error. Sending messages at a set interval for this purpose is also
known as a &quot;heartbeat&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;For Server Sent Events, heartbeats should be implemented using
&lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;Server-sent_events&#x2F;Using_server-sent_events#Event_stream_format&quot;&gt;comments&lt;&#x2F;a&gt;.
These are empty messages that are ignored by client implementations.&lt;&#x2F;p&gt;
&lt;p&gt;The WebSocket specification provides
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tungstenite&#x2F;0.9.2&#x2F;tungstenite&#x2F;protocol&#x2F;frame&#x2F;struct.Frame.html#method.ping&quot;&gt;&lt;code&gt;ping&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
and &lt;code&gt;pong&lt;&#x2F;code&gt; frames that can be used to maintain a heartbeat with a peer.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;interface-overview&quot;&gt;Interface overview&lt;&#x2F;h3&gt;
&lt;p&gt;These are the interfaces we&#x27;re proposing for the various channel interfaces:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::sync::{Sender, Receiver};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The messages sent and received by Tide&amp;#39;s channels.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub enum &lt;&#x2F;span&gt;&lt;span&gt;Message {
&lt;&#x2F;span&gt;&lt;span&gt;    Text(String),
&lt;&#x2F;span&gt;&lt;span&gt;    Binary(Vec&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    Ping,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;From&amp;lt;String&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Message {};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;From&amp;lt;Vec&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Message {};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;TryFrom&amp;lt;Message&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;String {};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;TryFrom&amp;lt;Message&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Vec&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The websocket interface.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;WebSocket((Sender, Receiver));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;WebSocket {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;is_open&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, impl Into&amp;lt;Message&amp;gt;) -&amp;gt; io::Result&amp;lt;()&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;send_json&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &amp;amp;impl Serialize) -&amp;gt; io::Result&amp;lt;()&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;recv&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; io::Result&amp;lt;Message&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;recv_json&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T: DeserializeOwned&amp;gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; io::Result&amp;lt;T&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Stream&amp;lt;Item = Message&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;WebSocket {};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The server sent events interface.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;ServerSentEvents(Sender);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;ServerSentEvents {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The id of the next message.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;is_open&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, impl Into&amp;lt;Message&amp;gt;) -&amp;gt; io::Result&amp;lt;()&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;send_json&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &amp;amp;impl Serialize) -&amp;gt; io::Result&amp;lt;()&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Impls on Tide&amp;#39;s Request struct
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Request {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;ws&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; WebSocket;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;sse&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; ServerSentEvents;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And these are the interfaces for the various endpoints and endpoint constructors:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Top-level functions to create an SSE endpoint
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;sse&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; ServerSendEventsEndpoint;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;sse_with&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;: impl AsyncFn&amp;lt;ServerSentEvents&amp;gt;) -&amp;gt; ServerSendEventsEndpoint;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Top-level function to create an SSE endpoint
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;ws&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; WebSocketEndpoint;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;ws_with&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;: impl AsyncFn&amp;lt;WebSocket&amp;gt;) -&amp;gt; WebSocketEndpoint;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The SSE endpoint struct.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;ServerSentEventsEndpoint(fn: Option&amp;lt;AsyncFn&amp;lt;_&amp;gt;&amp;gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;ServerSentEventsEndpoint {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;with&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span&gt;: impl AsyncFn&amp;lt;ServerSentEvents&amp;gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;set_timeout&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;tide::Endpoint &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;ServerSentEventsEndpoint {};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The Websocket endpoint struct.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;WebSocketEndpoint(fn: Option&amp;lt;AsyncFn&amp;lt;_&amp;gt;&amp;gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;WebSocketEndpoint {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;with&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span&gt;: impl AsyncFn&amp;lt;WebSocketEndpoint&amp;gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;set_timeout&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;tide::Endpoint &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;WebSocketEndpoint {};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;future-directions&quot;&gt;Future directions&lt;&#x2F;h2&gt;
&lt;p&gt;This post currently only describes a &lt;em&gt;design&lt;&#x2F;em&gt; for channels in Tide. Logical
next steps would include: implementation, feedback, and stabilization. But
looking beyond that, there are some features that don&#x27;t haven&#x27;t been fleshed
out yet.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;group-support&quot;&gt;Group support&lt;&#x2F;h3&gt;
&lt;p&gt;The APIs we&#x27;ve described so far only operate on individual channels. Inside
an HTTP request it&#x27;s clear which channel is connected to the client. But what
if you want to send messages over channels connected to different clients?
This often means manually writing grouping logic to keep track of who belongs
to which group.&lt;&#x2F;p&gt;
&lt;p&gt;In &lt;a href=&quot;https:&#x2F;&#x2F;hexdocs.pm&#x2F;phoenix&#x2F;channels.html#content&quot;&gt;Phoenix channels&lt;&#x2F;a&gt;, all
channels are grouped under &lt;em&gt;topics&lt;&#x2F;em&gt;, which makes it easy to send messages to
multiple channels. This is great for features such as group chat, or
real-time collaboration.&lt;&#x2F;p&gt;
&lt;p&gt;For Tide we want it to be possible to create groups, but do that as an
extension of singular APIs. Unlike Phoenix, a design goal here is to &lt;em&gt;not&lt;&#x2F;em&gt;
require a specialized client library to interact with Tide&#x27;s channels. Tide
should be flexible enough to replace existing production servers, without
requiring a redesign of the client logic. A rough API sketch:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; app = tide::new();
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;wss&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(tide::ws());
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;room&#x2F;:name&#x2F;join&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;post&lt;&#x2F;span&gt;&lt;span&gt;(async |req| {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; group_name = format!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;room:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, req.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;params&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?);
&lt;&#x2F;span&gt;&lt;span&gt;    req.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;ws&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join_group&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;group_name).await;
&lt;&#x2F;span&gt;&lt;span&gt;    req.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;ws&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;broadcast&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;group_name, format!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt; has joined the room&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, req.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;peer_addr&lt;&#x2F;span&gt;&lt;span&gt;())).await?;
&lt;&#x2F;span&gt;&lt;span&gt;    Response::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;listen&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In the example above all we provide is a mechanism to more conveniently
address peers that are also connected to the same server. In real-world
servers this would probably abstracted into a set of shared logic,
implemented as a &lt;code&gt;RequestExt&lt;&#x2F;code&gt;. This would allow abstracting the
stringly typed APIs into a reusable interface throughout the application:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;my_app::RequestExt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; app = tide::new();
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;wss&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(tide::ws());
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;room&#x2F;:name&#x2F;join&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;post&lt;&#x2F;span&gt;&lt;span&gt;(async |req| {
&lt;&#x2F;span&gt;&lt;span&gt;    req.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;room&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;().await?;
&lt;&#x2F;span&gt;&lt;span&gt;    req.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;room&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;broadcast&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;test, test&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;span&gt;    Response::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;listen&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;http-2-push-streams&quot;&gt;HTTP&#x2F;2 push streams&lt;&#x2F;h3&gt;
&lt;p&gt;On the surface HTTP&#x2F;2 push and SSE appear to have much in common. Both enable
sending messages from the server to the client, without the client requesting
them. However they&#x27;re intended for slightly different purposes.&lt;&#x2F;p&gt;
&lt;p&gt;In practice HTTP&#x2F;2 push is being designed to best handle &lt;em&gt;static&lt;&#x2F;em&gt; resources.
Specs such as &lt;a href=&quot;https:&#x2F;&#x2F;httpwg.org&#x2F;http-extensions&#x2F;cache-digest.html&quot;&gt;Cache Digests for
HTTP&#x2F;2&lt;&#x2F;a&gt; making their
way in, and packages such as
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;google&#x2F;node-h2-auto-push&quot;&gt;node-h2-auto-push&lt;&#x2F;a&gt; are turning
HTTP&#x2F;2 push into something that works really well for that.&lt;&#x2F;p&gt;
&lt;p&gt;In contrast SSE support in devtools is improving, and becoming easier to
inspect and debug small messages sent by the server. The different protocols
are being optimized for different purposes, and that&#x27;s valid &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#push&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;push&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;For more on HTTP&#x2F;2 push, I can recommend the article: &lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;the-node-js-collection&#x2F;node-js-can-http-2-push-b491894e1bb1&quot;&gt;&quot;Node.js can
HTTP&#x2F;2
push!&quot;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;However if we were to expose an API for it, it&#x27;d probably be along these
lines &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#push_api&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; app = tide::new();
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;index.html&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(async |req| {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; res = Response::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    res.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;set_body&lt;&#x2F;span&gt;&lt;span&gt;(Path::new(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;.&#x2F;assets&#x2F;index.html&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; css = Response::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    css.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;set_body&lt;&#x2F;span&gt;&lt;span&gt;(Path::new(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;.&#x2F;assets&#x2F;bundle.css&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;));
&lt;&#x2F;span&gt;&lt;span&gt;    res.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;bundle.css&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, css);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(res)
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;listen&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;push_api&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;The main consideration for any HTTP&#x2F;2 push API is that we stay
true to Tide&#x27;s Request&#x2F;Response model. This is analogous to &lt;a href=&quot;https:&#x2F;&#x2F;nodejs.org&#x2F;api&#x2F;http2.html#http2_response_createpushresponse_headers_callback&quot;&gt;the Node.js HTTP&#x2F;2
&lt;code&gt;response.createPushResponse()&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
API that&#x27;s part of the HTTP&#x2F;1 compat layer. The step after this would
probably be to build cache-aware auto-push middleware, but that comes later.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve shared the motivation, constraints, and proposed design
for Tide&#x27;s channels APIs. These APIs cover support for Server Sent Events,
and WebSockets.&lt;&#x2F;p&gt;
&lt;p&gt;In addition we&#x27;ve looked ahead for ways we can extend these APIs to work with
&quot;groups&quot;, and shared a rough draft of an HTTP&#x2F;2 push interface as well.&lt;&#x2F;p&gt;
&lt;p&gt;As I said at the start of this post, this one is a bit different than usual.
Today is January 29th 2020, and the entirety of this post was drafted and
published in a single day. This means there&#x27;s a fair chance designs laid out
here might have shortcomings, and will change over time. But I wanted to get
ahead of the curve, and share the research and motivations underlying these
designs.&lt;&#x2F;p&gt;
&lt;p&gt;My personal takeaway from researching the various channel APIs for Tide, is
that channels present a really nice interface, and lots of network things can
probably be expressed as channels! I&#x27;ve used both Server Sent Events and
WebSockets before, but they never really felt right. I think with this API we
might be onto something that could make this easier.&lt;&#x2F;p&gt;
&lt;p&gt;Either way that&#x27;s about all I can share for now. It&#x27;s back to writing
different posts. Happy Wednesday!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Byte Ordered Streams</title>
            <pubDate>Wed, 22 Jan 2020 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/byte-ordered-stream-parsing/</link>
            <guid>https://blog.yoshuawuyts.com/byte-ordered-stream-parsing/</guid>
            <description>&lt;p&gt;While on vacation in Japan I dug into streaming parsing, for fun. It&#x27;s
something that piqued my interest ever since I saw Mafintosh&#x27;s
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mafintosh&#x2F;csv-parser&quot;&gt;&lt;code&gt;csv-parser&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; package back in 2014.&lt;&#x2F;p&gt;
&lt;p&gt;This led to the creation of the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;omnom&quot;&gt;&lt;code&gt;omnom&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; library
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#omnom&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, and as part of it I came up with an ergonomic way to parse and
write numbers with a specified endianness to and from streams. An example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::fs::File;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;omnom::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; file = File::open(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;foo.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write_le&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;56_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;)?;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Write an i32 as little-endian to a byte stream.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; n: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16 &lt;&#x2F;span&gt;&lt;span&gt;= file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_be&lt;&#x2F;span&gt;&lt;span&gt;()?;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Read a u16 as big-endian from a byte stream.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; n: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span&gt;= file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_be&lt;&#x2F;span&gt;&lt;span&gt;()?;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Read a u32 as big-endian from a byte stream.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;omnom&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;The name &lt;code&gt;omnom&lt;&#x2F;code&gt; is a pun on the excellent
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;nom&#x2F;5.1.0&#x2F;nom&#x2F;&quot;&gt;&lt;code&gt;nom&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; package, which you should probably
check out if you&#x27;re looking to write a maintainable parser.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;bytes-and-endianness&quot;&gt;Bytes and Endianness&lt;&#x2F;h2&gt;
&lt;p&gt;&quot;Endianness&quot; is a word that you might hear occasionally, but if you&#x27;ve never
written network drivers or serialization formats you might not have had to
learn about before. Basically what it means is &quot;the order in which bytes form numbers&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;A byte is the smallest representation of data in a computer, and in Rust it&#x27;s
referred to as a &lt;code&gt;u8&lt;&#x2F;code&gt;. A &lt;code&gt;u16&lt;&#x2F;code&gt; is two bytes long, which means it&#x27;s two &lt;code&gt;u8&lt;&#x2F;code&gt;s.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b1 = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;];      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; length 1 byte, size equal to u8
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b2 = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; length 2 bytes, size equal to u16
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However in the second case, do we interpret the bytes from left-to-right, or
right-to-left? Endianness refers to the order we read bytes in. Little-endian
means we interpret bytes right-to-left. And big-endian means we interpret
them left-to-right. Different protocols will interpret bytes in different
orders, but it will usually say so in the protocol. The most important thing
to be aware of is that there&#x27;s a difference between the two.&lt;&#x2F;p&gt;
&lt;p&gt;In Rust&#x27;s stdlib there exists &quot;little-endian&quot;, &quot;big-endian&quot;, and
&quot;native-endian&quot;. The latter refers to the system&#x27;s default representation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;reading-bytes-from-a-stream&quot;&gt;Reading Bytes from a stream&lt;&#x2F;h2&gt;
&lt;p&gt;Say we wanted to read a &lt;code&gt;u16&lt;&#x2F;code&gt; encoded as little-endian from a stream. We
would write something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::io::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::fs::File;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::mem;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; f = File::open(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;foo.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; buf = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; mem::size_of::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;()];
&lt;&#x2F;span&gt;&lt;span&gt;f.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_exact&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; buf)?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; num = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;::from_le_bytes(buf);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This uses &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;mem&#x2F;fn.size_of.html&quot;&gt;&lt;code&gt;mem::size_of&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
to ensure we get the right size for the type we&#x27;re trying to read. Then uses
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;io&#x2F;trait.Read.html#method.read_exact&quot;&gt;&lt;code&gt;Read::read_exact&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
to read bytes from the stream, and
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;io&#x2F;trait.Read.html#method.read_exact&quot;&gt;&lt;code&gt;u16::from_le_bytes&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
to convert it to a u16 &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#methods&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;methods&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;If you haven&#x27;t seen the bytes methods before: they&#x27;re fairly new,
and have been implemented as part of Rust 1.32. In the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;52963&quot;&gt;tracking
issue&lt;&#x2F;a&gt; there&#x27;s a fair bit of
talk about operating on streams. Which is what we&#x27;re trying to improve today with this post (:&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;To write a u16 as little-endian to a stream, we can do:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::io::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::fs::File;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; file = File::create(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;foo.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write_all&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;99_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_le_bytes&lt;&#x2F;span&gt;&lt;span&gt;())?; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Write a u16 to a stream.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This approach uses
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;primitive.u16.html#method.to_le_bytes&quot;&gt;&lt;code&gt;u16::to_le_bytes&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
and
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;io&#x2F;trait.Write.html#method.write_all&quot;&gt;&lt;code&gt;Write::write_all&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
to write bytes to a stream.&lt;&#x2F;p&gt;
&lt;p&gt;As you can see writing bytes to a stream is somewhat straight forward;
combining two API calls to create the buffer and write it. But expressively
reading bytes is much more involved: a combination of 3 APIs that must be
used in the right order to read from a stream.&lt;&#x2F;p&gt;
&lt;p&gt;Having to write this for each number read from a stream would feel
repetitive, making it harder to read and write. But it&#x27;s also not very
discoverable for people who want to use these APIs. In order to figure it out
you have to learn about several different APIs, and the interaction between
them &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#doc search&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;doc search&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;For the sake of this post I put together these examples. I
know this is anecdotal evidence, but it took me about 10 minutes to find the
right APIs and make something that compiles. This is after having written a
library that makes extensive use of both. The end-result of the std APIs
might look pretty decent when presented as-is. But we shouldn&#x27;t underestimate
the time it takes to find the APIs and make them work together.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;readbytes-writebytes&quot;&gt;ReadBytes &#x2F; WriteBytes&lt;&#x2F;h2&gt;
&lt;p&gt;The
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.Iterator.html#method.collect&quot;&gt;&lt;code&gt;Iterator::collect&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
function is one of the functions that best embodies Rust&#x27;s values of
expressiveness, performance, and correctness. There&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;blog.jcoglan.com&#x2F;2019&#x2F;04&#x2F;22&#x2F;generic-returns-in-rust&#x2F;&quot;&gt;entire
articles&lt;&#x2F;a&gt;
written about just that one function. And rightfully so; it&#x27;s because of the
type system and the borrow checker that we can have a single API that can
just as easily convert an &lt;code&gt;Iterator&lt;&#x2F;code&gt; to a &lt;code&gt;HashMap&lt;&#x2F;code&gt;, as to a &lt;code&gt;Result&amp;lt;Vec&amp;gt;&lt;&#x2F;code&gt; --
all without any performance penalty. That&#x27;s quite impressive for a language
that has such a strong focus on correctness as Rust.&lt;&#x2F;p&gt;
&lt;p&gt;It turns out we can write a similar API for number encoding and decoding
number types as well. In &lt;code&gt;omnom&lt;&#x2F;code&gt; we&#x27;ve done this by implementing two traits for
each number:
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;omnom&#x2F;3.0.0&#x2F;omnom&#x2F;trait.ReadBytes.html&quot;&gt;&lt;code&gt;ReadBytes&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;omnom&#x2F;3.0.0&#x2F;omnom&#x2F;trait.WriteBytes.html&quot;&gt;&lt;code&gt;WriteBytes&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#naming&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. The
APIs look like this:&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;naming&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;I&#x27;m not particularly attached to the naming of these methods. It&#x27;s
mostly that alternatives that I came up with, such as &lt;code&gt;ByteOrderedRead&lt;&#x2F;code&gt;,
seemed really long. If this ever makes it to an RFC, the naming of traits is
something might need to be reconsidered.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use&lt;&#x2F;span&gt;&lt;span&gt; std:io::{Read, Write};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;ReadBytes: Sized {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read_be&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;R: Read&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;reader&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; R) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read_le&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;R: Read&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;reader&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; R) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read_ne&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;R: Read&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;reader&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; R) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;WriteBytes {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;write_be&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;W: Write&amp;gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;writer&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; W) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;write_le&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;W: Write&amp;gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;writer&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; W) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;write_ne&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;W: Write&amp;gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;writer&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; W) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We implement this for each individual number type so that it knows how to
encode and decode itself from streams. We then add various endian-based
read&#x2F;write methods to the &lt;code&gt;Read&lt;&#x2F;code&gt; and &lt;code&gt;Write&lt;&#x2F;code&gt; traits that can take any &lt;code&gt;T: ReadBytes&lt;&#x2F;code&gt; or &lt;code&gt;T: WriteBytes&lt;&#x2F;code&gt; and write it to themselves:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;ReadExt: Read + Sized {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read_be&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;B: ReadBytes&amp;gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Result&amp;lt;B&amp;gt; { ... }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read_le&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;B: ReadBytes&amp;gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Result&amp;lt;B&amp;gt; { ... }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read_ne&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;B: ReadBytes&amp;gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Result&amp;lt;B&amp;gt; { ... }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;WriteExt: Write + Sized {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;write_be&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;B: WriteBytes&amp;gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;num&lt;&#x2F;span&gt;&lt;span&gt;: B) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; { ... }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;write_le&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;B: WriteBytes&amp;gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;num&lt;&#x2F;span&gt;&lt;span&gt;: B) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; { ... }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;write_ne&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;B: WriteBytes&amp;gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;num&lt;&#x2F;span&gt;&lt;span&gt;: B) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; { ... }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T: Read&amp;gt; ReadExt &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;T {}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;T: Write&amp;gt; WriteExt &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;T {}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When put together, this allow reading and writing bytes from any number type
since they all implement &lt;code&gt;ReadBytes&lt;&#x2F;code&gt; and &lt;code&gt;WriteBytes&lt;&#x2F;code&gt;. This removes all
boilerplate we saw earlier, and replaces it with a few straight forward APIs.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::fs::File;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;omnom::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; file = File::open(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;foo.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write_le&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;56_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;)?;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; write an i32 as little-endian to a stream.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; n: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16 &lt;&#x2F;span&gt;&lt;span&gt;= file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_be&lt;&#x2F;span&gt;&lt;span&gt;()?;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; read a u16 as big-endian from a stream.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;future-possibilities&quot;&gt;Future possibilities&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;rfc&quot;&gt;RFC&lt;&#x2F;h3&gt;
&lt;p&gt;Making people use the &lt;code&gt;omnom&lt;&#x2F;code&gt; library for such a small API addition doesn&#x27;t
make much sense. I think this would be a fantastic addition to the standard
library, making something commonplace both easier to author, review, and
learn about. Perhaps this would make for a good RFC?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;floating-point-numbers&quot;&gt;Floating point numbers&lt;&#x2F;h3&gt;
&lt;p&gt;Since Rust 1.41 endianness conversions are now available for floats as well.
This isn&#x27;t part of &lt;code&gt;omnom&lt;&#x2F;code&gt; yet, but would be a 2-line change to add.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;multi-value-reads-and-writes&quot;&gt;Multi-value reads and writes&lt;&#x2F;h3&gt;
&lt;p&gt;Something else that would be a lot of fun to add would be multi-value reads
and writes:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Proposed
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; head: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;] = file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_be&lt;&#x2F;span&gt;&lt;span&gt;()?;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Current
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b1: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span&gt;= file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_be&lt;&#x2F;span&gt;&lt;span&gt;()?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b2: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span&gt;= file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_be&lt;&#x2F;span&gt;&lt;span&gt;()?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b3: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span&gt;= file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_be&lt;&#x2F;span&gt;&lt;span&gt;()?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b4: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span&gt;= file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_be&lt;&#x2F;span&gt;&lt;span&gt;()?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; head = [b1, b2, b3, b4];
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;support-for-async-streams&quot;&gt;Support for async streams&lt;&#x2F;h3&gt;
&lt;p&gt;Another interesting avenue to explore would be to implement these methods for
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.3.1&#x2F;futures&#x2F;io&#x2F;trait.AsyncRead.html&quot;&gt;&lt;code&gt;AsyncRead&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
and
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.3.1&#x2F;futures&#x2F;io&#x2F;trait.AsyncWrite.html&quot;&gt;&lt;code&gt;AsyncWrite&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
Reading bytes asynchronously from streams is very common, which would create
benefits comparable to their synchronous counterparts.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::fs::File;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;omnom::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; file = File::open(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;foo.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write_le&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;56_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;).await?;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; write an i32 as little-endian to a byte stream.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; n: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16 &lt;&#x2F;span&gt;&lt;span&gt;= file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_be&lt;&#x2F;span&gt;&lt;span&gt;().await?;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; read a u16 as big-endian from a byte stream.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In &lt;code&gt;async-std&lt;&#x2F;code&gt; we&#x27;ve implemented
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.4.0&#x2F;async_std&#x2F;stream&#x2F;trait.Stream.html#method.collect&quot;&gt;&lt;code&gt;Stream::collect&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
using &lt;code&gt;FromStream&lt;&#x2F;code&gt; and &lt;code&gt;IntoStream&lt;&#x2F;code&gt; traits. I recently wrote about &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;streams-concurrency&#x2F;#creating-streams-from-collections&quot;&gt;the
challenges of these
traits&lt;&#x2F;a&gt;,
and given how similar they&#x27;d be to the traits we&#x27;re proposing in this post,
they&#x27;d likely face the same challenges. In short: we can probably implement
them today, but not as efficient as theoretically possible until we support
&lt;code&gt;async fn&lt;&#x2F;code&gt; in traits.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;alternatives&quot;&gt;Alternatives&lt;&#x2F;h2&gt;
&lt;p&gt;Back in November I wrote a &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;async-rs&#x2F;async-std&#x2F;issues&#x2F;578#issue-527577429&quot;&gt;rather long survey of byte-ordered reads and
writes&lt;&#x2F;a&gt;,
and discussed a few alternatives. The design implemented in &lt;code&gt;omnom&lt;&#x2F;code&gt; ended up
being the third option we discussed. But it&#x27;s probably worthwhile discussing
the other two options we considered.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;alternative-1-inherent-methods-on-read-write&quot;&gt;Alternative 1: Inherent Methods on Read&#x2F;Write&lt;&#x2F;h3&gt;
&lt;p&gt;Instead of implementing a new trait for each number type, we could add
number-specific methods on the &lt;code&gt;Read&lt;&#x2F;code&gt; and &lt;code&gt;Write&lt;&#x2F;code&gt; traits. If we followed
std&#x27;s naming conventions of prefixing with &lt;code&gt;be_&lt;&#x2F;code&gt;, &lt;code&gt;le_&lt;&#x2F;code&gt;, and &lt;code&gt;ne_&lt;&#x2F;code&gt; we would
end up implementing 96 new methods on &lt;code&gt;Read&lt;&#x2F;code&gt; and &lt;code&gt;Write&lt;&#x2F;code&gt; (2 traits * 3
endianness kinds * 16 number types).&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::io::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; reader = Cursor::new(vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;517&lt;&#x2F;span&gt;&lt;span&gt;, reader.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_u16_be&lt;&#x2F;span&gt;&lt;span&gt;()?);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;768&lt;&#x2F;span&gt;&lt;span&gt;, reader.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_u16_be&lt;&#x2F;span&gt;&lt;span&gt;()?);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s a lot of methods that would be shown in the documentation of &lt;code&gt;Read&lt;&#x2F;code&gt;
and &lt;code&gt;Write&lt;&#x2F;code&gt;, making it generally harder to browse and explore. But it would
also prevent us from implementing multi-value reads &#x2F; writes later on (see
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;byte-ordered-stream-parsing&#x2F;#future-possibilities&quot;&gt;Future Possibilities&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;alternative-2-byteorder-inspired&quot;&gt;Alternative 2: ByteOrder inspired&lt;&#x2F;h3&gt;
&lt;p&gt;Another option would be to follow
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;byteorder&#x2F;1.3.2&#x2F;byteorder&#x2F;&quot;&gt;byteorder&lt;&#x2F;a&gt;&#x27;s approach of adding
32 methods on the Read and Write traits, and using &lt;code&gt;Endianness&lt;&#x2F;code&gt; types as type
parameters to choose the endianness.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::io::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::io::BigEndian;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; reader = Cursor::new(vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;517&lt;&#x2F;span&gt;&lt;span&gt;, reader.read_u16::&amp;lt;BigEndian&amp;gt;()?);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;768&lt;&#x2F;span&gt;&lt;span&gt;, reader.read_u16::&amp;lt;BigEndian&amp;gt;()?);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Compared to the first option that&#x27;s still a lot of methods (16 per trait),
and would also prevent us from implementing multi-value read&#x2F;writes later on.
Additionally we would need to introduce at least 3 additional &lt;code&gt;Endianness&lt;&#x2F;code&gt;
types that are used to switch between endianness, which means additional
imports in order to use the traits &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#endian types&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub mod &lt;&#x2F;span&gt;&lt;span&gt;io {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub mod &lt;&#x2F;span&gt;&lt;span&gt;endian {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;BigEndian;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;LittleEndian;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;NativeEndian;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;endian types&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;Unfortunately Rust&#x27;s current type system does not support
constraining generic paramaters by enum members. This means that &quot;endianness&quot;
needs to have 3 different structs instead of a single enum containing
different kinds of endianness. When added to the stdlib it might make sense
to create a submodule for this so that it still feels like we&#x27;d be
contraining by an enum&#x27;s member, even if we aren&#x27;t actually doing that.
Because familiarity and all.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;prior-art&quot;&gt;Prior Art&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;byteorder&quot;&gt;byteorder&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;byteorder&#x2F;1.3.2&#x2F;byteorder&quot;&gt;&lt;code&gt;byteorder&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate uses a
variation of the second alternative. &lt;code&gt;byteorder&lt;&#x2F;code&gt; was one of the first crates
to provide convenience APIs for byte order aware operations, so the naming
predates the additions to the stdlib.&lt;&#x2F;p&gt;
&lt;p&gt;As of Rust 1.32 numeric types have started to provide built-in methods such
as &lt;code&gt;to_le&lt;&#x2F;code&gt; and &lt;code&gt;from_le&lt;&#x2F;code&gt; that partially cover the same functionality as
&lt;code&gt;byteorder&lt;&#x2F;code&gt;. The purpose of this post is to share additional designs that
could replace the remaining uses of &lt;code&gt;byteorder&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tokio-byteorder&quot;&gt;tokio-byteorder&lt;&#x2F;h3&gt;
&lt;p&gt;The
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio-byteorder&#x2F;0.2.0&#x2F;tokio_byteorder&#x2F;&quot;&gt;&lt;code&gt;tokio-byteorder&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
crate is a port of &lt;code&gt;byteorder&lt;&#x2F;code&gt; for &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio&quot;&gt;&lt;code&gt;tokio&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&#x27;s own
&lt;code&gt;AsyncRead&lt;&#x2F;code&gt; and &lt;code&gt;AsyncWrite&lt;&#x2F;code&gt; traits. The design mostly matches &lt;code&gt;byteorder&lt;&#x2F;code&gt;,
with the exception that it operates on asynchronous byte streams instead of
synchronous ones.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::io::Cursor;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;tokio_byteorder::{BigEndian, AsyncReadBytesExt};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; rdr = Cursor::new(vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;517&lt;&#x2F;span&gt;&lt;span&gt;, rdr.read_u16::&amp;lt;BigEndian&amp;gt;().await?);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;768&lt;&#x2F;span&gt;&lt;span&gt;, rdr.read_u16::&amp;lt;BigEndian&amp;gt;().await?);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;tokio&quot;&gt;tokio&lt;&#x2F;h3&gt;
&lt;p&gt;Two months ago &lt;code&gt;tokio&lt;&#x2F;code&gt; added support for
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio&#x2F;0.2.9&#x2F;tokio&#x2F;io&#x2F;trait.AsyncReadExt.html#method.read_u16&quot;&gt;reading&lt;&#x2F;a&gt;
and
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio&#x2F;0.2.9&#x2F;tokio&#x2F;io&#x2F;trait.AsyncWriteExt.html#method.write_u16&quot;&gt;writing&lt;&#x2F;a&gt;
numbers as big-endian only:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;tokio::io::{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, AsyncReadExt};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::io::Cursor;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; reader = Cursor::new(vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;517&lt;&#x2F;span&gt;&lt;span&gt;, reader.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_u16&lt;&#x2F;span&gt;&lt;span&gt;().await?);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;768&lt;&#x2F;span&gt;&lt;span&gt;, reader.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_u16&lt;&#x2F;span&gt;&lt;span&gt;().await?);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This currently includes 20 new methods total for &lt;code&gt;AsyncRead&lt;&#x2F;code&gt; and
&lt;code&gt;AsyncWrite&lt;&#x2F;code&gt;. &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tokio-rs&#x2F;tokio&#x2F;pull&#x2F;1915&quot;&gt;A design&lt;&#x2F;a&gt; to add
support for little-endian writes has been proposed, which closely follows the
&lt;a href=&quot;http:&#x2F;&#x2F;127.0.0.1:1111&#x2F;streaming-parsing&#x2F;#alternative-1-inherent-methods-on-read-write&quot;&gt;first alternative we
outlined&lt;&#x2F;a&gt;
(e.g. &lt;code&gt;write_u16_le&lt;&#x2F;code&gt;). If accepted it would introduce an additional 40
top-level methods for &lt;code&gt;AsyncRead&lt;&#x2F;code&gt; and &lt;code&gt;AsyncWrite&lt;&#x2F;code&gt;. At the time of writing
&lt;code&gt;tokio&lt;&#x2F;code&gt; equivalents of stdlib features such as support for floating point
numbers or platform-native endianness do not seem to have been proposed.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;nom&quot;&gt;nom&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;nom&quot;&gt;&lt;code&gt;nom&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is a parser-combinator library that operates on
byte buffers instead of streams. As such it isn&#x27;t quite the same as the
others in this list. However it does have support for streaming operations,
and &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;nom&#x2F;5.1.0&#x2F;nom&#x2F;number&#x2F;streaming&#x2F;index.html&quot;&gt;provides several
methods&lt;&#x2F;a&gt; to read
bytes with a given endianness:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;nom::number::streaming::be_u16;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;parser &lt;&#x2F;span&gt;&lt;span&gt;= |&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;| {
&lt;&#x2F;span&gt;&lt;span&gt;  be_u16::&amp;lt;(_, ErrorKind)&amp;gt;(s)
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;parser&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\x00\x01&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;abcd&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;), Ok((&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;abcd&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;[..], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0x0001&lt;&#x2F;span&gt;&lt;span&gt;)));
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;parser&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\x01&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;), Err(Err::Incomplete(Needed::Size(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;))));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This approach is different from any API we&#x27;ve discussed so far, though the
naming scheme somewhat matches the first alternative.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve covered what endianness is, why streaming parsing is
useful, and showed how byte-ordered aware parsing can be performed today.
We&#x27;ve then gone on to introduce a novel approach for streaming byte-ordered
aware parsing, inspired by the stdlib&#x27;s &lt;code&gt;collect&lt;&#x2F;code&gt; function, and shown how to
use a reference implementation. We then covered alternative API designs we
and prior art.&lt;&#x2F;p&gt;
&lt;p&gt;I originally wanted to publish this post in early December after I came
back from Japan. But the holidays happened, so I figured I&#x27;d make the effort
now that we&#x27;re approaching the end of the first month of the new year.&lt;&#x2F;p&gt;
&lt;p&gt;Overall I&#x27;m pretty excited about this API. It&#x27;s very close to: &quot;What if
collect worked for numbers?&quot;; being able to read and write numbers using 3
new methods on each trait. I think that&#x27;s something that would be really
nice.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; head: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;] = file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_be&lt;&#x2F;span&gt;&lt;span&gt;()?;
&lt;&#x2F;span&gt;&lt;span&gt;file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write_le&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;56_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;)?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;Thanks to Joshua Gould (Technetos) and Florian Gilcher (Skade) for
proof-reading this post.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Streams Concurrency</title>
            <pubDate>Sat, 21 Dec 2019 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/streams-concurrency/</link>
            <guid>https://blog.yoshuawuyts.com/streams-concurrency/</guid>
            <description>&lt;p&gt;In our last post about Async Rust we looked at &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;futures-concurrency&#x2F;&quot;&gt;Futures
concurrency&lt;&#x2F;a&gt;, and before that
we looked at &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;rust-streams&#x2F;&quot;&gt;Rust streams&lt;&#x2F;a&gt;. In this
post we bring the two together, and will take a closer look at concurrency with
Rust streams.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;primer-data-modeling&quot;&gt;Primer: Data Modeling&lt;&#x2F;h2&gt;
&lt;p&gt;Much of async programming is about modeling relationships in code. So before we
dig into streams concurrency, it&#x27;s worth talking about the relationships we&#x27;re
trying to model first.&lt;&#x2F;p&gt;
&lt;p&gt;In the wild you may see relationships expressed as &quot;M:1&quot; or
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;sync&#x2F;mpsc&#x2F;index.html&quot;&gt;&quot;MPSC&quot;&lt;&#x2F;a&gt;, but all they are
is descriptors of relationships. &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;graphs&#x2F;&quot;&gt;I&#x27;ve written about these relationships
before&lt;&#x2F;a&gt; if you&#x27;re interested in learning
more. But for the sake of this post, here&#x27;s a brief overview:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Relationship&lt;&#x2F;th&gt;&lt;th&gt;Kind&lt;&#x2F;th&gt;&lt;th&gt;Graph Kind&lt;&#x2F;th&gt;&lt;th&gt;Channel Kind&lt;&#x2F;th&gt;&lt;th&gt;Example&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;one-to-one&lt;&#x2F;td&gt;&lt;td&gt;1:1&lt;&#x2F;td&gt;&lt;td&gt;List&lt;&#x2F;td&gt;&lt;td&gt;SPSC&lt;&#x2F;td&gt;&lt;td&gt;Iterating over stream output in a loop.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;one-to-many&lt;&#x2F;td&gt;&lt;td&gt;1:N&lt;&#x2F;td&gt;&lt;td&gt;Tree&lt;&#x2F;td&gt;&lt;td&gt;SPMC&lt;&#x2F;td&gt;&lt;td&gt;Writing stream output to multiple destination channels.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;many-to-one&lt;&#x2F;td&gt;&lt;td&gt;N:1&lt;&#x2F;td&gt;&lt;td&gt;Tree&lt;&#x2F;td&gt;&lt;td&gt;MPSC&lt;&#x2F;td&gt;&lt;td&gt;Combining multiple streams into a single stream.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;many-to-many&lt;&#x2F;td&gt;&lt;td&gt;M:N&lt;&#x2F;td&gt;&lt;td&gt;Graph&lt;&#x2F;td&gt;&lt;td&gt;MPMC&lt;&#x2F;td&gt;&lt;td&gt;An event bus where each node can both emit and listen.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;In theory any of the relationships can be expressed in terms of any other
relationship. But in practice using constructs that were actually designed for
the relationship is much nicer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;one-to-one&quot;&gt;one-to-one&lt;&#x2F;h2&gt;
&lt;img src=&quot;&#x2F;assets&#x2F;streams-concurrency&#x2F;one-to-one.jpg&quot; alt=&quot;a sequence of nodes&quot; style=&quot;max-width:300px&quot;&gt;
&lt;p&gt;The most basic way of processing a stream is in a sequence. For each element
produced in the stream we perform an operation. We guaranteed a new operation is
run only after the previous operation has ended.&lt;&#x2F;p&gt;
&lt;p&gt;In today&#x27;s Rust this is usually written using a &lt;code&gt;while let Some &#x2F; await&lt;&#x2F;code&gt; loop or
&lt;code&gt;for_each&lt;&#x2F;code&gt; stream adapter:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = stream::repeat(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(num) = a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().await {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, num);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = stream::repeat(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;for_each&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;num&lt;&#x2F;span&gt;&lt;span&gt;| println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, num))
&lt;&#x2F;span&gt;&lt;span&gt;    .await;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;for_each&lt;&#x2F;code&gt; and &lt;code&gt;while let Some&lt;&#x2F;code&gt; loops are mostly comparable. The only difference
is that the &lt;code&gt;for_each&lt;&#x2F;code&gt; cannot use &lt;code&gt;break&lt;&#x2F;code&gt; or &lt;code&gt;continue&lt;&#x2F;code&gt; statements the way
&lt;code&gt;while let Some&lt;&#x2F;code&gt; loops can.&lt;&#x2F;p&gt;
&lt;p&gt;Serial parsing of streams is most comparable to synchronous loops. But
instead of blocking between iterations of the loop, it waits for the task
without blocking any threads through an executor. Just like serial processing
of iterators is a common operation, so is serial processing of streams.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;many-to-one&quot;&gt;many-to-one&lt;&#x2F;h2&gt;
&lt;img src=&quot;&#x2F;assets&#x2F;streams-concurrency&#x2F;many-to-one.jpg&quot; alt=&quot;many nodes convering to a single node&quot; style=&quot;max-width:400px&quot;&gt;
&lt;p&gt;Sometimes you want to combine multiple streams into a single stream. For example
there might be a stream of events coming from a network connection, and a series
of events coming from another part of the system through a local channel. You
may want to combine these into a single stream of events. In &lt;code&gt;async-std&lt;&#x2F;code&gt; we
expose 3 ways of combining streams:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;0.99.12&#x2F;async_std&#x2F;stream&#x2F;trait.Stream.html#method.chain&quot;&gt;chain&lt;&#x2F;a&gt;:&lt;&#x2F;strong&gt; exhaust &quot;a&quot;, then exhaust &quot;b&quot;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;0.99.12&#x2F;async_std&#x2F;stream&#x2F;trait.Stream.html#method.zip&quot;&gt;zip&lt;&#x2F;a&gt;:&lt;&#x2F;strong&gt; combine &quot;a&quot; and &quot;b&quot; into a stream of tuples.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;0.99.12&#x2F;async_std&#x2F;stream&#x2F;trait.Stream.html#method.merge&quot;&gt;merge&lt;&#x2F;a&gt;:&lt;&#x2F;strong&gt; combine &quot;a&quot; and &quot;b&quot; into a stream that outputs items from either
as they become ready.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Both &lt;code&gt;chain&lt;&#x2F;code&gt; and &lt;code&gt;zip&lt;&#x2F;code&gt; have counterparts in &lt;code&gt;std::Iterator&lt;&#x2F;code&gt;. However &lt;code&gt;merge&lt;&#x2F;code&gt; is
a novel API we&#x27;ve introduced as part of &lt;code&gt;async_std&lt;&#x2F;code&gt;. It allows awaiting two
streams in parallel, as if they were a single stream. To see why let&#x27;s take a
look at how we might solve this without &lt;code&gt;Stream::merge&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Define shared inner loop logic.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;num&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;num: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, num);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Exhaust the first stream in one thread.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = task::spawn(async {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; nums = stream::repeat(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(num) = nums.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().await {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(num);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Exhaust the second stream in another thread.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = task::spawn(async {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; nums = stream::repeat(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(num) = nums.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().await {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(num);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Wait until both streams have been exhausted
&lt;&#x2F;span&gt;&lt;span&gt;a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(b).await;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However with &lt;code&gt;Stream::merge&lt;&#x2F;code&gt; we can greatly reduce this logic by creating a
single stream that yields items from both streams as soon as they become
available, and spawning fewer tasks in the process:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = stream::repeat(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = stream::repeat(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; nums = a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;merge&lt;&#x2F;span&gt;&lt;span&gt;(b);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(num) = nums.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().await {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;num: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, num);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;one-to-many&quot;&gt;one-to-many&lt;&#x2F;h2&gt;
&lt;img src=&quot;&#x2F;assets&#x2F;streams-concurrency&#x2F;one-to-many.jpg&quot; alt=&quot;a single node being converted into multiple nodes&quot; style=&quot;max-width:300px&quot;&gt;
&lt;p&gt;Going from a single stream to multiple streams is a bit trickier than what we&#x27;ve
seen before. But luckily Rust makes this easy through the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;sync&#x2F;mpsc&#x2F;fn.channel.html&quot;&gt;&lt;code&gt;channel&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
abstraction. And as part of &lt;code&gt;async-std&lt;&#x2F;code&gt; we&#x27;ve built a channel impl that&#x27;s both
easy &lt;em&gt;and&lt;&#x2F;em&gt; performant.&lt;&#x2F;p&gt;
&lt;p&gt;Channels always come in pairs. When you create a new channel, you get back a
tuple of &lt;code&gt;(Sender, Receiver)&lt;&#x2F;code&gt;. Whenever a value is written from a &lt;code&gt;Sender&lt;&#x2F;code&gt;, it&#x27;s
received by a &lt;code&gt;Receiver&lt;&#x2F;code&gt;. Both structs implement &lt;code&gt;Clone&lt;&#x2F;code&gt;, &lt;code&gt;Send&lt;&#x2F;code&gt;, and &lt;code&gt;Sync&lt;&#x2F;code&gt; so
they can freely be shared around between as many threads and tasks as you want.
&lt;code&gt;Receiver&lt;&#x2F;code&gt; also implements &lt;code&gt;Stream&lt;&#x2F;code&gt; which makes it easy to read values with.&lt;&#x2F;p&gt;
&lt;p&gt;In the following example we split a stream of numbers into two streams: one of
even numbers, and one of uneven numbers. We pass both &lt;code&gt;Sender&lt;&#x2F;code&gt;s on one side,
which means that from the other side we&#x27;re now free to read values from either
stream.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::stream;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::sync;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(even_reader, even_writer) = sync::channel(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(uneven_reader, uneven_writer) = sync::channel(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; num_stream = stream::repeat(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(num) = num_stream.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().await {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; num % &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;=&amp;gt; even_writer.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(num).await;
&lt;&#x2F;span&gt;&lt;span&gt;        _ =&amp;gt; uneven_writer.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(num).await;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; We can now asynchronously read from `even_reader`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; and `uneven_reader` in separate tasks.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Channels in &lt;code&gt;async-std&lt;&#x2F;code&gt; are incredibly versatile. They&#x27;re very similar to event
emitters in other languages, and can often be used in similar scenarios. The
only difference is that channels in &lt;code&gt;async-std&lt;&#x2F;code&gt; currently don&#x27;t support sending
values from a single reader to &lt;em&gt;all&lt;&#x2F;em&gt; receivers; but that&#x27;s something we&#x27;re
considering adding. This would allow our streams to model many-to-many
relationships as well.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;collecting-streams&quot;&gt;Collecting Streams&lt;&#x2F;h2&gt;
&lt;img src=&quot;&#x2F;assets&#x2F;streams-concurrency&#x2F;collect.jpg&quot; alt=&quot;many nodes convering to a single node&quot; style=&quot;max-width:300px&quot;&gt;
&lt;p&gt;Often times when a computation is over you&#x27;d like to store the results
somewhere. An example is printing to stdout, but also collecting all output in a
vector. In std this is done through &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.Iterator.html#method.collect&quot;&gt;&lt;code&gt;Iterator::collect&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Similarly with
streams this can be done through &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;0.99.9&#x2F;async_std&#x2F;stream&#x2F;trait.Stream.html#method.collect&quot;&gt;&lt;code&gt;Stream::collect&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The trick to making &lt;code&gt;collect&lt;&#x2F;code&gt; work is the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;0.99.9&#x2F;async_std&#x2F;stream&#x2F;trait.FromStream.html&quot;&gt;&lt;code&gt;FromStream&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; trait. This converts a
stream into a type asynchronously. In &lt;code&gt;async-std&lt;&#x2F;code&gt; we&#x27;ve implemented this for a
lot of std&#x27;s types. When combined with some of the other stream types this
allows for creating really nice pipeline patterns.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create a stream of tuples, and collect into a hashmap.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = stream::once(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = stream::once(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; s = a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;zip&lt;&#x2F;span&gt;&lt;span&gt;(b);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; map: HashMap&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; = s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span&gt;().await;
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;), Some(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are even more interesting patterns possible; for example if you have a
stream of &lt;code&gt;Result&amp;lt;T, E&amp;gt;&lt;&#x2F;code&gt; you could collect into a &lt;code&gt;Result&amp;lt;Vec&amp;lt;T&amp;gt;, E&amp;gt;&lt;&#x2F;code&gt;. This
allows short-circuiting the stream as soon as an error occurs.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::stream;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; v = stream::from_iter(vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res: Result&amp;lt;Vec&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static str&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; = v.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;|
&lt;&#x2F;span&gt;&lt;span&gt;    x.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;checked_add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;ok_or&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Overflow!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span&gt;().await;
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(res, Ok(vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;creating-streams-from-collections&quot;&gt;Creating streams from collections&lt;&#x2F;h2&gt;
&lt;p&gt;The
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.4.0&#x2F;async_std&#x2F;stream&#x2F;trait.IntoStream.html&quot;&gt;&lt;code&gt;IntoStream&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
trait implements how to convert any type into a stream. It&#x27;s the asynchronous
counterpart to
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.IntoIterator.html&quot;&gt;&lt;code&gt;IntoIterator&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; sync
&lt;&#x2F;span&gt;&lt;span&gt;vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;for_each&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;| dbg!(n));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; async, proposed
&lt;&#x2F;span&gt;&lt;span&gt;vec![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;stream&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;for_each&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;| dbg!(n)).await;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Unfortunately due to the orphan rules we&#x27;re currently not able to implement
&lt;code&gt;IntoStream&lt;&#x2F;code&gt; for any of the &lt;code&gt;std::collection&lt;&#x2F;code&gt; types. This would need to happen
as part of &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-core&#x2F;0.3.1&#x2F;futures_core&#x2F;&quot;&gt;&lt;code&gt;futures-core&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
because that is where the &lt;code&gt;Stream&lt;&#x2F;code&gt; trait is defined.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;d also love to propose adding &lt;code&gt;FromStream&lt;&#x2F;code&gt; to &lt;code&gt;futures-core&lt;&#x2F;code&gt;, but
unfortunately it&#x27;s hard to implement without language support for &lt;code&gt;async fn&lt;&#x2F;code&gt; in
traits. In &lt;code&gt;async-std&lt;&#x2F;code&gt; &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.4.0&#x2F;async_std&#x2F;stream&#x2F;trait.FromStream.html#tymethod.from_stream&quot;&gt;we require a
&lt;code&gt;Pin&amp;lt;Box&amp;lt;T&amp;gt;&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
as the return type, which is less efficient than what we&#x27;d want it to be. And
for &lt;code&gt;collect&lt;&#x2F;code&gt; to work, we really need both traits.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cancelling-streams&quot;&gt;Cancelling streams&lt;&#x2F;h2&gt;
&lt;p&gt;Often it&#x27;s desirable to stop a stream remotely. If we want to shut down
gracefully often the first step is to stop processing new data. And that&#x27;s
something that needs to be initialized remotely.&lt;&#x2F;p&gt;
&lt;p&gt;For that we have the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;async-rs&#x2F;stop-token&quot;&gt;&lt;code&gt;stop-token&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
crate. An experimental stream built on top of channels that provides remote
cancellation of streams:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;stop_token::StopToken;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;do_work&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;work&lt;&#x2F;span&gt;&lt;span&gt;: impl Stream&amp;lt;Item = Event&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;stop_token&lt;&#x2F;span&gt;&lt;span&gt;: StopToken) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The `work` stream will end early: as soon as `stop_token` is cancelled.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; work = stop_token.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;stop_stream&lt;&#x2F;span&gt;&lt;span&gt;(work);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(event) = work.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().await {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;process_event&lt;&#x2F;span&gt;&lt;span&gt;(event).await
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We think cancellation is something that should be easy to do, and &lt;code&gt;stop-token&lt;&#x2F;code&gt;
is a first attempt at implementing that. All credit to
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;matklad&quot;&gt;matklad&lt;&#x2F;a&gt; for this.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;parallel-streams&quot;&gt;Parallel Streams&lt;&#x2F;h2&gt;
&lt;img src=&quot;&#x2F;assets&#x2F;streams-concurrency&#x2F;parallel.jpg&quot; alt=&quot;a single stream becoming multiple streams becoming a single stream again&quot; style=&quot;max-width:400px&quot;&gt;
&lt;p&gt;A common pattern when processing data is to create a &lt;a href=&quot;http:&#x2F;&#x2F;zguide.zeromq.org&#x2F;page:all#Divide-and-Conquer&quot;&gt;parallel fan-out &#x2F; fan-in
pipeline&lt;&#x2F;a&gt;. Say we have a
stream of data; we&#x27;d like to process that data in parallel. And once it&#x27;s done
processing, we either &lt;code&gt;collect&lt;&#x2F;code&gt; it, or iterate over values one-by-one.&lt;&#x2F;p&gt;
&lt;p&gt;In synchronous Rust you can choose to hand-write such a pipeline, or perhaps use
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;crossbeam&#x2F;0.7.3&#x2F;crossbeam&#x2F;fn.scope.html&quot;&gt;&lt;code&gt;crossbeam::scope&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
But the nicest way of pipelining data is still &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rayon&quot;&gt;&lt;code&gt;rayon&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The way &lt;code&gt;rayon&lt;&#x2F;code&gt; works is by providing a parallel version of
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.Iterator.html&quot;&gt;&lt;code&gt;Iterator&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; called
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rayon&#x2F;1.3.0&#x2F;rayon&#x2F;iter&#x2F;trait.ParallelIterator.html&quot;&gt;&lt;code&gt;ParallelIterator&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
that, as its name implies allows processing iterators in parallel. Going from
sequential execution to parallel execution usually means just replacing &lt;code&gt;iter&lt;&#x2F;code&gt;
with &lt;code&gt;par_iter&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;rayon::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;sum_of_squares&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;input&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;]) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    input.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;par_iter&lt;&#x2F;span&gt;&lt;span&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; &amp;lt;-- just change that!
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;| i * i)
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Similarly we should be able to apply this model to &lt;code&gt;Stream&lt;&#x2F;code&gt; by introducing a new
&lt;code&gt;ParallelStream&lt;&#x2F;code&gt; trait that operates on items in parallel by calling
&lt;code&gt;task::spawn&lt;&#x2F;code&gt; under the hood. All that would be needed would be an added call to
&lt;code&gt;par&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;parallel_stream::prelude::*;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;sum_of_squares&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;input&lt;&#x2F;span&gt;&lt;span&gt;: impl Stream&amp;lt;Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    input.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;par&lt;&#x2F;span&gt;&lt;span&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; &amp;lt;-- just add that!
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;| i * i)
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;        .await
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Unfortunately despite being fairly convinced that this is possible to implement,
we currently don&#x27;t have an implementation of besides &lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;yoshuawuyts&#x2F;182721650d1858ea25f7590ac0384d8d&quot;&gt;this
sketch&lt;&#x2F;a&gt;.
If you&#x27;d like to help out on &lt;code&gt;parallel-stream&lt;&#x2F;code&gt;, let us know on
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;async-rs&#x2F;async-std&quot;&gt;GitHub&lt;&#x2F;a&gt; or
&lt;a href=&quot;https:&#x2F;&#x2F;discord.gg&#x2F;JvZeVNe&quot;&gt;Discord&lt;&#x2F;a&gt; and we&#x27;ll gladly help. We really want to
see this exist!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;concurrency-in-futures-rs&quot;&gt;Concurrency in futures-rs&lt;&#x2F;h2&gt;
&lt;p&gt;You may have noticed that we haven&#x27;t mentioned the
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.3.1&#x2F;futures&#x2F;&quot;&gt;&lt;code&gt;futures&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; library much. In part that
is because it doesn&#x27;t provide many abstractions that work with executors. But
let&#x27;s take a quick look at the stream concurrency abstractions that are provided:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-preview&#x2F;0.3.0-alpha.19&#x2F;futures&#x2F;stream&#x2F;futures_unordered&#x2F;index.html&quot;&gt;&lt;code&gt;stream::futures_unordered&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;: a &lt;code&gt;Set&lt;&#x2F;code&gt; of futures that can resolve in any order..&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-preview&#x2F;0.3.0-alpha.19&#x2F;futures&#x2F;stream&#x2F;trait.StreamExt.html#method.for_each_concurrent&quot;&gt;&lt;code&gt;StreamExt::for_each_concurrent&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;: a concurrent version of &lt;code&gt;Stream::for_each&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-preview&#x2F;0.3.0-alpha.19&#x2F;futures&#x2F;stream&#x2F;trait.StreamExt.html#method.try_for_each_concurrent&quot;&gt;&lt;code&gt;StreamExt::try_for_each_concurrent&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;: a concurrent version of &lt;code&gt;Stream::try_for_each&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.3.1&#x2F;futures&#x2F;macro.select.html&quot;&gt;&lt;code&gt;select!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;: Polls multiple futures and streams simultaneously, executing the
branch for the future that finishes first.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;code&gt;futures_unordered&lt;&#x2F;code&gt;, &lt;code&gt;for_each_concurrent&lt;&#x2F;code&gt;, and friends occupy roughly the same
space as &lt;code&gt;ParallelStream&lt;&#x2F;code&gt;. But &lt;code&gt;ParallelStream&lt;&#x2F;code&gt; has the benefit that it should
be a bit more flexible, and make better use of system resources by leveraging an
executor.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.3.1&#x2F;futures&#x2F;macro.select.html&quot;&gt;&lt;code&gt;select!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is an abstraction which is somewhat similar to &lt;code&gt;match&lt;&#x2F;code&gt; but operates
on streams and futures directly. But it&#x27;s not without its shortcoming. &lt;code&gt;select!&lt;&#x2F;code&gt;
introduces a two new keywords: &lt;code&gt;default&lt;&#x2F;code&gt; and &lt;code&gt;complete&lt;&#x2F;code&gt;. It requires all futures
and streams to be manually fused. And has also required &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.3.1&#x2F;futures&#x2F;stream&#x2F;trait.FusedStream.html&quot;&gt;changes in
&lt;code&gt;futures&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; that have created deviations from the stdlib, which is a cost in
itself.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a_fut = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;async_identity_fn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;fuse&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b_fut = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;async_identity_fn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;fuse&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; total = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    select! {
&lt;&#x2F;span&gt;&lt;span&gt;        a = a_fut =&amp;gt; total += a,
&lt;&#x2F;span&gt;&lt;span&gt;        b = b_fut =&amp;gt; total += b,
&lt;&#x2F;span&gt;&lt;span&gt;        complete =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        default =&amp;gt; panic!(), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; never runs (futures run first, then complete)
&lt;&#x2F;span&gt;&lt;span&gt;    };
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(total, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It seems that as we&#x27;re moving towards extending the stdlib with more of
&lt;code&gt;futures&lt;&#x2F;code&gt;&#x27; core types, we&#x27;ll eventually need to provide a solution on how to
operate on streams. And because there&#x27;s no precedent for including a macro as
complex as &lt;code&gt;select!&lt;&#x2F;code&gt; in the stdlib, it seems likely it would either need to be
upgraded to a language construct, or we would need to look at alternatives that
&lt;em&gt;can&lt;&#x2F;em&gt; be included.&lt;&#x2F;p&gt;
&lt;p&gt;With &lt;code&gt;async-std&lt;&#x2F;code&gt; we&#x27;ve chosen to look for alternatives instead. And between
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;1.4.0&#x2F;async_std&#x2F;stream&#x2F;trait.Stream.html#method.merge&quot;&gt;&lt;code&gt;Stream::merge&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; for combining streams, and &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;stop-token&quot;&gt;&lt;code&gt;stop-token&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; for cancelling them
it seems we&#x27;re well on our way. But we&#x27;re not at the end of the road yet, and
we&#x27;d like to keep experimenting and documenting stream adapters until we
confidently can replace all uses of &lt;code&gt;select!&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;looking-ahead-language-support&quot;&gt;Looking Ahead: Language Support&lt;&#x2F;h2&gt;
&lt;p&gt;A bit further down the line it might be interesting to consider what language
support could look like for parallel Rust. If we can define parallel
counterparts to &lt;code&gt;Iterator&lt;&#x2F;code&gt; and &lt;code&gt;Stream&lt;&#x2F;code&gt;, it begs the question if we could also
define parallel counterparts to &lt;code&gt;loop&lt;&#x2F;code&gt;, &lt;code&gt;for&lt;&#x2F;code&gt;, and &lt;code&gt;while&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Take for example the following TCP server. It listens for incoming requests, and
processes them in sequence. It has a maximum concurrency of 1, but the code is
really easy to follow.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; listener = TcpListener::bind(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Listening on &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;local_addr&lt;&#x2F;span&gt;&lt;span&gt;()?);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; stream in listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;incoming&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; stream = stream?;
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Accepting from: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, stream.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;peer_addr&lt;&#x2F;span&gt;&lt;span&gt;()?);
&lt;&#x2F;span&gt;&lt;span&gt;    io::copy(&amp;amp;stream, &amp;amp;stream)?;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now if we try and parallelize the server using &lt;code&gt;async-std&lt;&#x2F;code&gt; today we can suddenly
handle thousands of requests concurrently, but the code itself is much less
readable. And worse, we can no longer pass errors from the inner scope back up
to the outer scope without calling &lt;code&gt;.await&lt;&#x2F;code&gt; on each &lt;code&gt;JoinHandle&lt;&#x2F;code&gt;, and making the
request handler serial again.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; listener = TcpListener::bind(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;span&gt;println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Listening on &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;local_addr&lt;&#x2F;span&gt;&lt;span&gt;()?);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(stream) = listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;incoming&lt;&#x2F;span&gt;&lt;span&gt;().await {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; stream = stream?;
&lt;&#x2F;span&gt;&lt;span&gt;    task::spawn(async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Accepting from: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, stream.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;peer_addr&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;        io::copy(&amp;amp;stream, &amp;amp;stream).await.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    });
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;An API such as &lt;code&gt;ParallelStream&lt;&#x2F;code&gt; would provide some alleviation here. It would
allow us to implement a parallel server without losing the ability to return
errors from scopes.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; listener = TcpListener::bind(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;span&gt;println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Listening on &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;local_addr&lt;&#x2F;span&gt;&lt;span&gt;()?);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;listener
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;incoming&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;par&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_for_each&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;stream&lt;&#x2F;span&gt;&lt;span&gt;| async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; stream = stream?;
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Accepting from: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, stream.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;peer_addr&lt;&#x2F;span&gt;&lt;span&gt;()?);
&lt;&#x2F;span&gt;&lt;span&gt;        io::copy(&amp;amp;stream, &amp;amp;stream).await?;
&lt;&#x2F;span&gt;&lt;span&gt;        Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;    })
&lt;&#x2F;span&gt;&lt;span&gt;    .await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But this suddenly feels very different from the API we started with. Code is
just as much about reading as it is about writing. And being able to spot loops
at a glance is very useful. So instead of only having chained operators,
wouldn&#x27;t it be nice if we could write &lt;em&gt;parallel loops&lt;&#x2F;em&gt; instead? Perhaps
something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; listener = TcpListener::bind(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;span&gt;println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Listening on &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;local_addr&lt;&#x2F;span&gt;&lt;span&gt;()?);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; par stream.await? in listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;incoming&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Accepting from: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, stream.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;peer_addr&lt;&#x2F;span&gt;&lt;span&gt;()?);
&lt;&#x2F;span&gt;&lt;span&gt;    io::copy(&amp;amp;stream, &amp;amp;stream).await?;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This again looks a lot like the synchronous TCP server we started with. But
instead of processing requests serially, it now uses all available cores without
blocking.&lt;&#x2F;p&gt;
&lt;p&gt;Now this is not so much a concrete proposal, as a sketch to share what things
&lt;em&gt;could&lt;&#x2F;em&gt; look like if we designed them that way. I&#x27;d like us to think big on
this; following the tradition of making seemingly complex concepts surprisingly
accessible. Not only would we be free of data races in parallel code. It&#x27;d be
incredibly convenient to write as well.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve looked at different variants of streams concurrency,
discussed the current state of support they have in Async Rust, and shared
avenues worth exploring to improve the status quo.&lt;&#x2F;p&gt;
&lt;p&gt;Personally I&#x27;m very excited about how this post has come together. I feel like
Rust is currently on a path to achieve what no other mainstream language has
achieved: to make writing parallel code not only correct and performant. But to
make it as easy as sequential code.&lt;&#x2F;p&gt;
&lt;p&gt;This might seem like a tall order, but between the diagnostics efforts, language
design, compiler work, and libraries it really feels like that&#x27;s where we&#x27;re
heading. And I couldn&#x27;t be more excited.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;Thanks to: Irina Shestak for the illustrations. And Stjepan Glavina, Sunjay
Varma, Niko Matsakis, Withoutboats, Aaron Turon, Aleksey Kladov, Ryan Levick,
and Friedel Ziegelmayer.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Rust 2020</title>
            <pubDate>Sat, 30 Nov 2019 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/rust-2020/</link>
            <guid>https://blog.yoshuawuyts.com/rust-2020/</guid>
            <description>&lt;p&gt;One month ago the Rust team put out &lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;2019&#x2F;10&#x2F;29&#x2F;A-call-for-blogs-2020.html&quot;&gt;a call for blogs
2020&lt;&#x2F;a&gt;. I quite
like these posts because it provides an occasion to provide perspective on all
of Rust, by everyone. In this post I&#x27;ll look back at Rust&#x27;s development over
2019, and cover topics that seem important for Rust 2020.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-state-of-rust&quot;&gt;The state of Rust&lt;&#x2F;h2&gt;
&lt;p&gt;According to the 2019 StackOverflow survey, 8 out of 10 people that have tried
Rust like it. But only &lt;a href=&quot;https:&#x2F;&#x2F;insights.stackoverflow.com&#x2F;survey&#x2F;2019&#x2F;#technology&quot;&gt;3% of
developers&lt;&#x2F;a&gt; are
actually using Rust. Compared to a language such as JavaScript that has almost
&lt;a href=&quot;https:&#x2F;&#x2F;insights.stackoverflow.com&#x2F;survey&#x2F;2019&#x2F;#technology&quot;&gt;2 out of 3 devs know and
use&lt;&#x2F;a&gt;, it seems we
still have a long way to go.&lt;&#x2F;p&gt;
&lt;p&gt;Rust is uniquely positioned in that it provides a good story for front-end (30%
of roles), back-end (50% of roles), and embedded (9% of roles)
(&lt;a href=&quot;https:&#x2F;&#x2F;insights.stackoverflow.com&#x2F;survey&#x2F;2019&#x2F;#developer-profile-_-developer-type&quot;&gt;src&lt;&#x2F;a&gt;).
These numbers overlap slightly as a single developer can fulfill multiple roles,
but Rust has a remarkably wide range of potential applications.&lt;&#x2F;p&gt;
&lt;p&gt;Rust is currently heading in the right direction to address the market’s needs.
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;polonius&quot;&gt;Polonius&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;chalk&quot;&gt;Chalk&lt;&#x2F;a&gt;, and improved diagnostics are chipping away at some of the
rough edges of working with the compiler. The WebAssembly WG has made Rust the
single best choice for use with WASM. And with &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; finally on stable
it seems we’re well on track to improve our presence in the web space as well.
The current path seems to be one that leads us to increased industry adoption,
which is a key component for Rust&#x27;s growth and success.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;editions&quot;&gt;Editions&lt;&#x2F;h2&gt;
&lt;p&gt;The core team has asked: “Should we have a Rust 2021 edition?” and the short
answer is: “Yes we should, even if we don&#x27;t intend to change much.”&lt;&#x2F;p&gt;
&lt;p&gt;Despite only having had a single edition so far, 3 years seems to be a healthy
pacing for editions. We had a release in 2015, another in 2018, and having
another release in 2021 would be in line with that. Just like we don’t expect
every 6-week release to be equally exciting, we shouldn’t expect each edition to
introduce groundbreaking new changes either.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Having a regular cadence at which we release changes makes Rust predictable&lt;&#x2F;strong&gt;.
This allows upstream vendors to anticipate toolchain upgrades. And allows
enterprise users (whose number is steadily growing) to become accustomed to the
6-week stable, 3-year edition cycle. This provides much needed stability in
a space that can feel like it’s moving at a high pace.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;timeline&quot;&gt;Timeline&lt;&#x2F;h3&gt;
&lt;p&gt;Like Rust 2018, we&#x27;ll likely aim to release Rust 2021 in Q3 of the same year.
If the last last 12 months of pacing are an indication of the pacing for next
year, we should account for 6 weeks per year where the Rust project operates at
a reduced pace (due to time off, travel, etc).&lt;&#x2F;p&gt;
&lt;p&gt;We should ensure all desired changes have completed their design +
implementation well before the deadline. The 2018 edition had its deadline moved
once last year, and even then ended up seeing some &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=As1gXp5kX1M&quot;&gt;stressful last-minute
backports&lt;&#x2F;a&gt;. I don&#x27;t think anyone is
keen on going through that again.&lt;&#x2F;p&gt;
&lt;p&gt;It seems wise to plan conservatively for the next edition, and aim to have all
planned edition changes on nightly for about 3 cycles, and in beta for 1 or 2
cycles. This roughly correlates to the progression &lt;code&gt;async&#x2F;await&lt;&#x2F;code&gt; had through the
release pipeline, and feature-wise shipping the next edition will likely be of
comparable scope. This amounts to a period of roughly 24-30 weeks.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;All together that leaves us with about 12 months total to plan and prepare the
next edition release, starting January 2020.&lt;&#x2F;strong&gt; This should be enough time to
successfully plan and draft a new edition, with some slack to work with.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;organization&quot;&gt;Organization&lt;&#x2F;h2&gt;
&lt;p&gt;Management, community, and governance seem to be the difficult topics for many
organizations. And we&#x27;re no different. Last year Boat’s laid out some of Rust’s
challenges in this area in their &lt;a href=&quot;https:&#x2F;&#x2F;boats.gitlab.io&#x2F;blog&#x2F;post&#x2F;rust-2019&#x2F;&quot;&gt;organizational
debt&lt;&#x2F;a&gt; post. In 2019 work has been
made to address some of these issues, so let&#x27;s review how we&#x27;ve done since:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GitHub isn’t a great fit for lang design:&lt;&#x2F;strong&gt; This still rings true, but &lt;a href=&quot;http:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2019&#x2F;07&#x2F;10&#x2F;aic-unbounded-queues-and-lang-design&#x2F;&quot;&gt;some
steps are being
taken&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Project coordination isn’t smooth:&lt;&#x2F;strong&gt; There is now a bi-weekly cross-team
meeting for all team leads. This is a good step, but alignment on vision still
seems like something to improve on (more on the importance of that later).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Teams are experiencing growing pains:&lt;&#x2F;strong&gt; This may have progressed the
most. I’ve been seeing regular announcements of co-leads introduced in teams,
and new sub-teams being split off to tackle specific issues.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Working groups need a toolkit:&lt;&#x2F;strong&gt; The overarching idea is to provide more
guidance with setting up teams. Given more sub-teams have been spun up
recently I’m assuming some progress has been made.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Community management is emotionally exhausting:&lt;&#x2F;strong&gt; It still is, and it seems
little progress has been made in 2019. We’ve lost good people because of this,
and we will continue to do so unless things change. It’s not good enough to
onboard new people, we must also ensure we’re able to retain them.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#retain&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;It’s time to talk about pay:&lt;&#x2F;strong&gt; Contributors to Rust are still mostly
unpaid. If we want people to see things through to completion they need to
have the bandwidth to. And that means being paid.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Even if we’re leaving 2019 better than we started it, there seems to be a lot of
work left to be done here. Organizational work is at the core of everything else
that happens in the project, and above all else this seems to be the one thing
we should keep improving. We’re growing fast, and our organization needs to grow
with it.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;retain&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Almost everybody involved in Rust I speak with regularly seems
exhausted. Too few people have too much on their plate, and that&#x27;s not a good
sign. What can we do about it though? My guess is somewhere between improving
processes, and better support infrastructure.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;language&quot;&gt;Language&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;lang-team&quot;&gt;Lang Team&lt;&#x2F;h3&gt;
&lt;p&gt;Over the past year I&#x27;ve been involved with the Lang Meta WG, whose goal it was
to identify the friction points the lang team has, and how to fix them.
Practical challenges with practical solutions. Niko wrote about some of the
&lt;a href=&quot;http:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2019&#x2F;07&#x2F;10&#x2F;aic-unbounded-queues-and-lang-design&#x2F;&quot;&gt;challenges lang design
faces&lt;&#x2F;a&gt;,
and some of the &lt;a href=&quot;http:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2019&#x2F;09&#x2F;11&#x2F;aic-shepherds-3-0&#x2F;&quot;&gt;steps that are being taken to help solve
it&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Looking back at 2018, one of the biggest feats of the lang team getting Futures
and &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; to stable. But this process wasn&#x27;t pleasant, and ended up
taking a toll on many.&lt;&#x2F;p&gt;
&lt;p&gt;The lang team has taken the right steps in identifying what caused these issues,
and proposing solutions to help solve them. There are many language features on
the team&#x27;s backlog (GATs, specialization, etc.) and the main blocker right now
seems to be the bandwidth to see them through to completion.&lt;&#x2F;p&gt;
&lt;p&gt;The lang team is doing the right thing with the Shepherds design,
ensuring people are responsible for features, and creating a space of focus --
rather then a place where it can feel like everyone needs to react to
everything, all the time.&lt;&#x2F;p&gt;
&lt;p&gt;It would be great if the language team would write more beyond the space of
RFCs and internal threads. Classics such as &lt;a href=&quot;https:&#x2F;&#x2F;aturon.github.io&#x2F;tech&#x2F;2018&#x2F;04&#x2F;24&#x2F;async-borrowing&#x2F;&quot;&gt;&quot;borrowing in async
code&quot;&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;boats.gitlab.io&#x2F;blog&#x2F;post&#x2F;2018-03-20-async-vi&#x2F;&quot;&gt;&quot;async await
VI: 6 weeks of great
progress&quot;&lt;&#x2F;a&gt;, and
&lt;a href=&quot;https:&#x2F;&#x2F;www.ralfj.de&#x2F;blog&#x2F;2019&#x2F;04&#x2F;30&#x2F;stacked-borrows-2.html&quot;&gt;&quot;stacked borrows
2.0&quot;&lt;&#x2F;a&gt; have done a
great job at looping the wider Rust community in on important developments.&lt;&#x2F;p&gt;
&lt;p&gt;Quantitatively speaking a small group of people produce the majority of these
posts, and despite their clear value writing writing posts is not an expected
part of the design process. We now have the &lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;inside-rust&#x2F;&quot;&gt;inside Rust
blog&lt;&#x2F;a&gt; so even the unblogged have a
venue they can publish their writing&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#unblogged&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.  I&#x27;d love to see more people
write more over the next year; as the amount of Rust users is projected to grow,
and we&#x27;ll need to continue improving our communication.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;unblogged&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;e.g. people without blogs. Like me prior to 2019.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;language-features&quot;&gt;Language Features&lt;&#x2F;h3&gt;
&lt;p&gt;In terms of language features I don&#x27;t really have priorities. I&#x27;m not on the
lang team, and don&#x27;t quite know the dependency tree for my fave features.&lt;&#x2F;p&gt;
&lt;p&gt;The only thing I would add is that since this would be the time to ramp-up the
efforts for a 2021 edition, it&#x27;d be good to look at which keywords may want to
be reserved in anticipation for this.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#lang_features&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; I don&#x27;t suspect we&#x27;ll have
changes that are quite as large as, say, changing how imports work. But it&#x27;s
something that probably needs to be covered. Extra good if this could be done in
a structured way, say, as an artifact of a shepherding effort.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;lang_features&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Syntax for delegation would be pretty amazing. This would&#x27;ve
been fantastic to have for the last few project&#x27;s I&#x27;ve worked on. It came up
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;pull&#x2F;2393&quot;&gt;in the last edition&lt;&#x2F;a&gt;, but was
put on hold.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;compiler&quot;&gt;Compiler&lt;&#x2F;h2&gt;
&lt;p&gt;I know little about the compiler, so I guess the best I can do is share that as
an onlooker: It seems that things keep progressing steadily and overall quite
good.&lt;&#x2F;p&gt;
&lt;p&gt;Whether it&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;inside-rust&#x2F;2019&#x2F;11&#x2F;25&#x2F;const-if-match.html&quot;&gt;&lt;code&gt;if&#x2F;else&#x2F;match&lt;&#x2F;code&gt; in const
contexts&lt;&#x2F;a&gt;.
Excellent
&lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;inside-rust&#x2F;2019&#x2F;11&#x2F;25&#x2F;const-if-match.html&quot;&gt;diagnostics&lt;&#x2F;a&gt;.
Or &lt;a href=&quot;https:&#x2F;&#x2F;tmandry.gitlab.io&#x2F;blog&#x2F;posts&#x2F;optimizing-await-2&#x2F;&quot;&gt;implementing
&lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.  It
seems a lot of care and thought goes into building the compiler; and it&#x27;s really
nice to see it improve. Not just in features, but in performance as well!&lt;&#x2F;p&gt;
&lt;p&gt;Similarly I feel the infra and release teams are doing a great job, and like,
I&#x27;m thankful for all the work they&#x27;re doing so folks like myself get to try out
all of our weird experiments on a platform that feels incredibly reliable.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;libraries&quot;&gt;Libraries&lt;&#x2F;h2&gt;
&lt;p&gt;The standard library is the shared core that underpins all of Rust. It&#x27;s
arguably on par with the language itself in defining how we structure our
programs.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;stable-popular-small&quot;&gt;Stable, Popular, Small&lt;&#x2F;h3&gt;
&lt;p&gt;In the past 4 years the Rust ecosystem has seen some impressive developments.
We now have a rich ecosystem of stable modules. And it seems the time is right
to start looking into whether we can include &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;bascule&#x2F;status&#x2F;1184523400913522689&quot;&gt;some of
that&lt;&#x2F;a&gt; into the stdlib.
Boats &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;withoutboats&#x2F;status&#x2F;1184797783921975296&quot;&gt;formulated a great
heuristic&lt;&#x2F;a&gt; for what
to include:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;stable, popular, and small is std&#x27;s bread and butter&quot;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Applying this label some obvious candidates for inclusion in stdlib are:
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;matches&quot;&gt;&lt;code&gt;matches&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;num_cpus&quot;&gt;&lt;code&gt;num_cpus&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;crossbeam&#x2F;0.7.1&#x2F;crossbeam&#x2F;fn.scope.html&quot;&gt;&lt;code&gt;crossbeam::scope&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.  There&#x27;s probably many
more, and in 2020 I would like to see the libs team move to include some of
these.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;errors&quot;&gt;Errors&lt;&#x2F;h3&gt;
&lt;p&gt;Additionally there seem to be some steps we could take to improve Rust&#x27;s error
handling story, solidifying existing patterns. I&#x27;ve &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;error-handling-survey&#x2F;&quot;&gt;recently written about
this&lt;&#x2F;a&gt;, but the conclusion was there is rough ecosystem consensus we need:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Some kind of replacement for &lt;code&gt;Box&amp;lt;dyn Error + Send + Sync + &#x27;static&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Some way of wrapping &lt;code&gt;Results&lt;&#x2F;code&gt; in &lt;code&gt;.context&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Some way to conveniently define new error types.&lt;&#x2F;li&gt;
&lt;li&gt;Some way to iterate over error causes (&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;58520&quot;&gt;#58520&lt;&#x2F;a&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Support for backtraces (&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;53487&quot;&gt;#53487&lt;&#x2F;a&gt;).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;communication&quot;&gt;Communication&lt;&#x2F;h3&gt;
&lt;p&gt;Similar to the lang team, I would love to see the libs team blog more in 2020.
External communication is a key factor in growing Rust while preserving our
identity. And given the importance of the standard library, contextualizing
design decisions is something we could use more of.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#blog example&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;blog example&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;For an example of what a &quot;libs team post&quot; looks like: &lt;a href=&quot;https:&#x2F;&#x2F;boats.gitlab.io&#x2F;blog&#x2F;post&#x2F;global-executors&#x2F;&quot;&gt;global
executors&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;tooling&quot;&gt;Tooling&lt;&#x2F;h2&gt;
&lt;p&gt;Rust is as a tool that enables the wider software industry to write software
that&#x27;s both correct and performant, even under deadlines. The fact that Rust is
a programming language is somewhat incidental; it just happens to be the best
way to achieve those goals.&lt;&#x2F;p&gt;
&lt;p&gt;Tooling in Rust is crucial. They make up a large part of &quot;Rust, the product&quot;
together with the docs, crates.io, and the compiler.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#product&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; As such an
effective way to talk about tooling is to talk about Rust as a whole, and the
experience we provide for users of Rust.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;product&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;Calling rust a &quot;product&quot; might sound odd at first. But if we look
beyond the price tag (free), it has all the hallmarks of a product. We&#x27;ve got
a value proposition, competition, design, and product positioning. Viewing
Rust as a product seems like a useful lens to think of how we could improve.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;onboarding&quot;&gt;Onboarding&lt;&#x2F;h3&gt;
&lt;p&gt;I recently drafted a small guide to onboard &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yoshuawuyts&#x2F;rust-for-js-people&quot;&gt;JavaScript people onto Rust&lt;&#x2F;a&gt;.
However the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yoshuawuyts&#x2F;rust-for-js-people#quick-start&quot;&gt;Quick Start&lt;&#x2F;a&gt; section isn&#x27;t very quick. It starts off by explaining
how to install &lt;code&gt;rustup&lt;&#x2F;code&gt;, only to proceed to explain &lt;code&gt;cargo-edit&lt;&#x2F;code&gt;,
&lt;code&gt;cargo-fmt&lt;&#x2F;code&gt;, &lt;code&gt;cargo-clippy&lt;&#x2F;code&gt;, and &lt;code&gt;cargo-watch&lt;&#x2F;code&gt;, and how to install them.
Some of these are rustup components, others are regular crates. And put together
getting started isn&#x27;t exactly &lt;em&gt;frictionless&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;And that&#x27;s not even explaining how to setup editors. Or use cases Rust promotes
such as embedded development and WebAssembly. Installing &lt;code&gt;rustup&lt;&#x2F;code&gt; and &lt;code&gt;rustc&lt;&#x2F;code&gt;
only installs a part of &quot;Rust, the product&quot;. Core pieces such as &lt;code&gt;cargo fmt&lt;&#x2F;code&gt; or
&lt;code&gt;cargo add&lt;&#x2F;code&gt; are not mentioned anywhere, and people either need to actively
search for them or find out about them from others.&lt;&#x2F;p&gt;
&lt;p&gt;Onboarding Rust shouldn&#x27;t be an 8 step process. It should match what people
expect on their respective platforms. And even better: we should explore ways we
can explain the different tools to people so their first experience isn&#x27;t one of
trial-and-error.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;continuous-integration&quot;&gt;Continuous Integration&lt;&#x2F;h3&gt;
&lt;p&gt;Running Rust as part of CI builds is not without issues. The most common way
people seem to be integrating Rust these days seems to be to copy and paste a
template from somewhere else.&lt;&#x2F;p&gt;
&lt;p&gt;This is not great for many reasons. But not in the least because libraries are
often not tested for multiple platforms, checking if a library compiles on
WebAssembly is often skipped, and cache management often has much to be desired.&lt;&#x2F;p&gt;
&lt;p&gt;Continuous Integration is a huge part of real-world Rust usage, yet we don&#x27;t
provide much guidance. Community projects such as &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;actions-rs&quot;&gt;actions-rs&lt;&#x2F;a&gt; have sprung up to
fill the gap, but even though they&#x27;re often of excellent quality, this feels
like a core workflow of &quot;Rust, the product&quot; that should be considered.&lt;&#x2F;p&gt;
&lt;p&gt;There are many steps we could take from here, and which is best depends on the
willingness of people involved, and overall bandwidth. But I wanted to put this
on the map as something we should be thinking about, but traditionally haven&#x27;t
much.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;consistency&quot;&gt;Consistency&lt;&#x2F;h3&gt;
&lt;p&gt;As &quot;Rust, the product&quot; is a single entity, the tools it&#x27;s made up of should be
consistent between each other. This means using the same names for the same
things across projects. But also using similar flags, a similar tone of voice,
and feel.&lt;&#x2F;p&gt;
&lt;p&gt;But Rust&#x27;s components should not just be consistent with each other. They should
also be approachable for people coming from other ecosystems. For example &lt;code&gt;cargo clippy&lt;&#x2F;code&gt; is a reference to a &lt;a href=&quot;https:&#x2F;&#x2F;knowyourmeme.com&#x2F;memes&#x2F;clippy&quot;&gt;meme&lt;&#x2F;a&gt; from
the 90s, and if you&#x27;re not in the joke the command makes no sense. As it&#x27;s being
considered &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;pull&#x2F;2476&quot;&gt;to become a cargo
built-in&lt;&#x2F;a&gt;, people are rightly
asking whether using a more conventional term might better match people&#x27;s
expectations.&lt;&#x2F;p&gt;
&lt;p&gt;Both internal and external consistency are crucial considerations in Rust&#x27;s
design. Rust as a language has a &lt;a href=&quot;https:&#x2F;&#x2F;words.steveklabnik.com&#x2F;the-language-strangeness-budget&quot;&gt;limited strangeness
budget&lt;&#x2F;a&gt;. But so
does Rust as a product.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;webassembly&quot;&gt;WebAssembly&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;wasm-on-the-server&quot;&gt;WASM on the server&lt;&#x2F;h3&gt;
&lt;p&gt;WebAssembly on the server has been seeing huge leaps forward over the past year.
WASI, the system interface for WebAssembly&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#wasi&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, has seen great development.
And with the &lt;a href=&quot;https:&#x2F;&#x2F;bytecodealliance.org&#x2F;articles&#x2F;announcing-the-bytecode-alliance&quot;&gt;announcement of the bytecode alliance&lt;&#x2F;a&gt; it seems some major players
have become stakeholders in WASM&#x27;s success.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;wasi&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;If you&#x27;re confused by what WASI is; I like to think of it as: &quot;What if
POSIX worked on &lt;em&gt;every&lt;&#x2F;em&gt; platform, and also had versioning and permissions
built in? And also wasn&#x27;t restricted just to filesystem APIs, but could
include high-level things as well.&quot; It almost sounds too good to be true, but
the people working on this are &lt;em&gt;incredible&lt;&#x2F;em&gt; so I&#x27;m somewhat optimistic they&#x27;ll
actually be able to pull this off.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Rust currently has one of the most mature WASM&#x2F;WASI toolchains of any language.
This has been greatly beneficial, as it allows &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=KFpU30xluxo&quot;&gt;Rust implementations to
influence specs, and in turn specs help guide the
implementations&lt;&#x2F;a&gt;. This seems like a
mutually beneficial relationship for both Rust and WASM, which would be great to
continue into the next year.&lt;&#x2F;p&gt;
&lt;p&gt;However in terms of production use I haven&#x27;t seen WASM being used much on the
server. Both Fastly and CloudFlare have products available, but it seems like
it&#x27;s still early days. Either way, this is just a long way of saying that the
direction Rust is currently on regarding WASM&#x2F;WASI seems right, and is something
we should continue into the next year.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;wasm-in-the-browser&quot;&gt;WASM in the browser&lt;&#x2F;h3&gt;
&lt;p&gt;WASM in the browser is an interesting one. While it feels that WASM on the
server is seeing a lot of active development, WASM in the browser seems to have
taken more of a backseat. However this year did see the release of the
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;js-sys&quot;&gt;&lt;code&gt;js-sys&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;web-sys&quot;&gt;&lt;code&gt;web-sys&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crates which provide the ability to bind to the full
range of APIs the browsers have to offer.&lt;&#x2F;p&gt;
&lt;p&gt;What I&#x27;d like to see in 2020 is to allow people to start building projects in
the browser. Rust could have a similar value proposition as Elm for browser
development; stable, type-checked applications that don&#x27;t crash and are a joy to
write. But unlike Elm, Rust covers a much wider range of applications, which
brings it closer to JavaScript&#x27;s value proposition of writing &quot;isomorphic code&quot;
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#isomorphic&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;isomorphic&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
&lt;p&gt;&quot;isomorphism&quot; is a term used a lot in JavaScript: it describes
code that works in both the browser and on the server. I have long suspected
&quot;isomorphic Rust&quot; could also be a thing, and having implemented an &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;surf&quot;&gt;HTTP
client&lt;&#x2F;a&gt; that works in both browser and server this seems
likely to be true.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;I don&#x27;t think there&#x27;s a &lt;em&gt;lot&lt;&#x2F;em&gt; of work required here for people to get started.
Now that &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; has landed on stable, and &lt;code&gt;{js,web}-sys&lt;&#x2F;code&gt; exist, the main
things we need to do are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Create an ergonomic Rust interface to the DOM.&lt;&#x2F;li&gt;
&lt;li&gt;Add a &lt;code&gt;serve&lt;&#x2F;code&gt; command to &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;wasm-pack&quot;&gt;&lt;code&gt;wasm-pack&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Write a short guide on how to do DOM-related tasks.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Much of this work has already in some form of another. But it doesn&#x27;t feel
&lt;em&gt;whole&lt;&#x2F;em&gt; yet; there&#x27;s still a lot left to do, and I hope people will find the
time in the next 12 months to do so.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;async&quot;&gt;Async&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; MVP was stabilized in Rust 1.39 three weeks ago. This has
marked a major milestone in Rust&#x27;s development, and has set us to start
exploring fields we&#x27;ve traditionally not had a strong presence in such as web
services and user interfaces.&lt;&#x2F;p&gt;
&lt;p&gt;I hope in 2020 we can continue the work that was done over the past year, and
continue to encourage innovation, but also standardize the things we have
consensus on. The &lt;a href=&quot;http:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2019&#x2F;11&#x2F;22&#x2F;announcing-the-async-interviews&quot;&gt;async
interviews&lt;&#x2F;a&gt;
seem like an excellent first step in finding what those are, and what should be
prioritized&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#interviews&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;From my work on &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&quot;&gt;&lt;code&gt;async-std&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; async closures seem like a high priority, followed
by async traits.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;interviews&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;&#x2F;sup&gt;
&lt;p&gt;I like the interviews approach a lot: gathering input from
stakeholders and summarizing it to prioritize feature development. I wish we
would do more of this.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post I&#x27;ve covered whether we should have a new edition, a rough timeline
for a new edition, and the different aspects of the Rust language. To summarize
what we&#x27;ve covered:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Yes, we should have a 2021 edition because operating on a predictable timeline
is good for vendors, community, and enterprise alike.&lt;&#x2F;li&gt;
&lt;li&gt;The bulk of the work for the 2021 release should be done during the calendar
year of 2020. This includes reserving keywords.&lt;&#x2F;li&gt;
&lt;li&gt;The language team has made great steps by acknowledging it has an issue of
&lt;a href=&quot;http:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2019&#x2F;07&#x2F;10&#x2F;aic-unbounded-queues-and-lang-design&#x2F;&quot;&gt;unbounded
queues&lt;&#x2F;a&gt;,
and has taken steps towards
&lt;a href=&quot;http:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2019&#x2F;09&#x2F;11&#x2F;aic-shepherds-3-0&#x2F;&quot;&gt;shepherding&lt;&#x2F;a&gt;.
This should be continued next year.&lt;&#x2F;li&gt;
&lt;li&gt;Thinking about Rust as a product is a useful lens, and among other things we
might want to think about our onboarding and CI flows.&lt;&#x2F;li&gt;
&lt;li&gt;WASM on the server seems to be progressing steadily, and with a bit of
attention we can improve our experience in the browser too.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I feel Rust 2020 will be a continuation of the work done in 2019. Which in turn
was a continuation of the work of 2018. And I suspect 2021 will be much the
same. I don&#x27;t think this is an accident: Rust knows what it&#x27;s trying to be, and
much of the work left to do is about polish, finishing things we&#x27;ve started, and
making things easier.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m very excited about where the Rust project is headed, and keen to see how
it&#x27;ll evolve as fields such as Async Rust and WebAssembly continue to expand.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Tide</title>
            <pubDate>Wed, 27 Nov 2019 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/tide/</link>
            <guid>https://blog.yoshuawuyts.com/tide/</guid>
            <description>&lt;p&gt;Today we&#x27;re happy to announce the release of &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tide&#x2F;0.4.0&#x2F;tide&quot;&gt;Tide 0.4.0&lt;&#x2F;a&gt;
which has an exciting new design. This post will (briefly) cover some of the
exciting developments around Tide, and where we&#x27;re heading.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;our-north-star&quot;&gt;Our north star&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; MVP was released as part of Rust 1.39 three weeks ago. We
still have a long way to go, and features such as async traits, async iteration
syntax, and async closures mean that the async code we&#x27;ll be writing in the
future probably will be different from how we do things today.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s why we&#x27;d like to start with sharing where we want to bring Tide in the
future, but can&#x27;t because we&#x27;re limited by the technology of our time. We&#x27;d like
to make Tide a blazing fast, request-response based, streaming web framework.
In typical Rust spirit: not compromising between ergonomics and performance.&lt;&#x2F;p&gt;
&lt;p&gt;Reply with &quot;hello world&quot;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; tide::Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; app = tide::new();
&lt;&#x2F;span&gt;&lt;span&gt;    app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(|_| &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Hello, world!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;listen&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Serialize + Deserialize JSON:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Deserialize, Serialize)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: String
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; tide::Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; app = tide::new();
&lt;&#x2F;span&gt;&lt;span&gt;    app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;submit&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;post&lt;&#x2F;span&gt;&lt;span&gt;(async |req| {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cat: Cat = req.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;body_json&lt;&#x2F;span&gt;&lt;span&gt;()?;
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;cat name: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, cat.name);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cat = Cat { name: &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;chashu&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;() };
&lt;&#x2F;span&gt;&lt;span&gt;        tide::Response::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;body_json&lt;&#x2F;span&gt;&lt;span&gt;(cat)
&lt;&#x2F;span&gt;&lt;span&gt;    });
&lt;&#x2F;span&gt;&lt;span&gt;    app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;listen&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Both examples are really short, but do quite a bit in terms of functionality.
We think using async Rust should be as easy as sync Rust, and as the lang
features progress this will become increasingly a reality.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tide-today&quot;&gt;Tide today&lt;&#x2F;h2&gt;
&lt;p&gt;Like we said, we&#x27;re not quite there yet. Today we&#x27;re releasing Tide 0.4.0, a
first step in this direction. Our &quot;hello world&quot; looks like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;async_std&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; io::Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; app = tide::new();
&lt;&#x2F;span&gt;&lt;span&gt;    app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(|_| async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{ &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Hello, world!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; });
&lt;&#x2F;span&gt;&lt;span&gt;    app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;listen&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Notice the extra &lt;code&gt;async move {}&lt;&#x2F;code&gt; inside the &lt;code&gt;get&lt;&#x2F;code&gt; handler? That&#x27;s because async
closures don&#x27;t exist yet, which means we need the block statements. But also
don&#x27;t have blanket impls for regular closures either.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Deserialize, Serialize)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Cat {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: String,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;async_std&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; io::Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; app = tide::new();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;submit&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;post&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;req&lt;&#x2F;span&gt;&lt;span&gt;: tide::Request&amp;lt;()&amp;gt;| async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cat: Cat = req.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;body_json&lt;&#x2F;span&gt;&lt;span&gt;().await.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;cat name: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, cat.name);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; cat = Cat {
&lt;&#x2F;span&gt;&lt;span&gt;            name: &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;chashu&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;        };
&lt;&#x2F;span&gt;&lt;span&gt;        tide::Response::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;body_json&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;cat).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    });
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;listen&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The JSON example similarly still has a way to go. In particular error handling
could &lt;em&gt;really&lt;&#x2F;em&gt; use some work. Notice the &lt;code&gt;unwrap&lt;&#x2F;code&gt;s? Yeah, not great. It&#x27;s pretty
high on our todo list to fix this. In general there&#x27;s still a bit of polish
missing, but we&#x27;re definitely on track.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-tide-architecture&quot;&gt;The Tide Architecture&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;request-response&quot;&gt;Request-Response&lt;&#x2F;h3&gt;
&lt;p&gt;A big change from prior Tide versions is that we&#x27;re now directly based on a
request-response model. This means that a &lt;code&gt;Request&lt;&#x2F;code&gt; goes in, and a &lt;code&gt;Response&lt;&#x2F;code&gt;
is returned. This might sound obvious, but for example Node.js uses
the &lt;a href=&quot;https:&#x2F;&#x2F;nodejs.org&#x2F;en&#x2F;about&#x2F;&quot;&gt;&lt;code&gt;res.end&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; callback to send back responses
rather than returning responses from functions.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;async fn(req: Request) -&amp;gt; Result&amp;lt;Response&amp;gt;;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;middleware&quot;&gt;Middleware&lt;&#x2F;h3&gt;
&lt;p&gt;Aside from requests and responses, Tide allows passing middleware, global state
and local state. Middleware wrap each request and response pair, allowing code
to be run before the endpoint, and after each endpoint. Additionally each
handler can choose to never yield to the endpoint and abort early. This is
useful for e.g. authentication middleware.&lt;&#x2F;p&gt;
&lt;p&gt;Tide 0.4.0 ships with a request logger based on the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;log&#x2F;0.4.8&#x2F;log&#x2F;&quot;&gt;&lt;code&gt;log&lt;&#x2F;code&gt;
crate&lt;&#x2F;a&gt; out of the box. This middleware will log
each request when it comes in, and each response when it goes out.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;tide::middleware::RequestLogger;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;async_std&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Result&amp;lt;(), std::io::Error&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; app = tide::new();
&lt;&#x2F;span&gt;&lt;span&gt;    app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;middleware&lt;&#x2F;span&gt;&lt;span&gt;(RequestLogger::new());
&lt;&#x2F;span&gt;&lt;span&gt;    app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(|_| async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{ &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Hello, world!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; });
&lt;&#x2F;span&gt;&lt;span&gt;    app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;listen&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Tide middleware works like a stack. A simplified example of the logger
middleware is something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;req&lt;&#x2F;span&gt;&lt;span&gt;: Request, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;: Next) -&amp;gt; Result&amp;lt;Response&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Incoming request from &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt; on url &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, req.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;peer_addr&lt;&#x2F;span&gt;&lt;span&gt;(), req.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;url&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().await?;
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Outgoin response with status &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, res.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;status&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;    res
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As a new request comes in, we perform some logic. Then we yield to the next
middleware (or endpoint, we don&#x27;t know when we yield to &lt;code&gt;next&lt;&#x2F;code&gt;), and once that&#x27;s
done, we return the Response. We can decide to not yield to &lt;code&gt;next&lt;&#x2F;code&gt; at any stage,
and abort early.&lt;&#x2F;p&gt;
&lt;p&gt;The sequence in which middleware is run is:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;     Tide
&lt;&#x2F;span&gt;&lt;span&gt;1.          7.  Middleware 1
&lt;&#x2F;span&gt;&lt;span&gt;==============
&lt;&#x2F;span&gt;&lt;span&gt;2.          6.  Middleware 2
&lt;&#x2F;span&gt;&lt;span&gt;==============
&lt;&#x2F;span&gt;&lt;span&gt;3.          5.  Middleware 3
&lt;&#x2F;span&gt;&lt;span&gt;==============
&lt;&#x2F;span&gt;&lt;span&gt;      4.        Endpoint
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;state&quot;&gt;State&lt;&#x2F;h3&gt;
&lt;p&gt;Middleware often needs to share values with the endpoint. This is done through
&quot;local state&quot;. Local state is built using a
&lt;a href=&quot;https:&#x2F;&#x2F;rustasync.github.io&#x2F;team&#x2F;2018&#x2F;11&#x2F;07&#x2F;tide-middleware.html&quot;&gt;&lt;code&gt;typemap&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
that&#x27;s available through &lt;code&gt;Request::local_state&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Global state is used when a complete application needs access to a particular
value. Examples of this include: database connections, websocket connections, or
network-enabled config. Every &lt;code&gt;Request&amp;lt;State&amp;gt;&lt;&#x2F;code&gt; has an inner value that must
implement &lt;code&gt;Send + Sync + Clone&lt;&#x2F;code&gt;, and can thus freely be shared between requests.&lt;&#x2F;p&gt;
&lt;p&gt;By default &lt;code&gt;tide::new&lt;&#x2F;code&gt; will use &lt;code&gt;()&lt;&#x2F;code&gt; as the shared state. But if you want to
create a new app with shared state you can do:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Shared state
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;MyState {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;db_port&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;async_std&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Result&amp;lt;(), std::io::Error&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; state = State { db_port: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;8083 &lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; app = tide::with_state(state);
&lt;&#x2F;span&gt;&lt;span&gt;    app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(|_| async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{ &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Hello, world!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; });
&lt;&#x2F;span&gt;&lt;span&gt;    app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;listen&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;extension-traits&quot;&gt;Extension Traits&lt;&#x2F;h3&gt;
&lt;p&gt;Sometimes having global and local context can require a bit of setup. There are
cases where it&#x27;d be nice if things were a little easier. This is why Tide
encourages people to write &lt;em&gt;extension traits&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;By using an &lt;em&gt;extension trait&lt;&#x2F;em&gt; you can extend &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tide&#x2F;0.4.0&#x2F;tide&#x2F;struct.Request.html&quot;&gt;&lt;code&gt;Request&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; or &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tide&#x2F;0.4.0&#x2F;tide&#x2F;struct.Response.html&quot;&gt;&lt;code&gt;Response&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; with more
functionality. For example, an authentication package could implement a
&lt;code&gt;user&lt;&#x2F;code&gt; method on &lt;code&gt;Request&lt;&#x2F;code&gt;, to access the authenticated user provided by
middleware. Or a GraphQL package could implement &lt;code&gt;body_graphql&lt;&#x2F;code&gt; methods for
&lt;code&gt;Request&lt;&#x2F;code&gt; and &lt;code&gt;Response&lt;&#x2F;code&gt; as counterparts to
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tide&#x2F;0.4.0&#x2F;tide&#x2F;struct.Request.html#method.body_json&quot;&gt;&lt;code&gt;body_json&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
so that serializing and deserializing GraphQL becomes easier.&lt;&#x2F;p&gt;
&lt;p&gt;More interesting even is the interplay between global &lt;code&gt;State&lt;&#x2F;code&gt;, derives, and
extension traits. There&#x27;s probably a world of ORM-adjacent extension that could
be construed. And probably much more we haven&#x27;t thought of; but we encourage you
to experiment and share what you come up with.&lt;&#x2F;p&gt;
&lt;p&gt;An extension trait in its base form is written as such:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;RequestExt {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;bark&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; String;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;State&amp;gt; RequestExt &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Request&amp;lt;State&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;bark&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; String {
&lt;&#x2F;span&gt;&lt;span&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;woof&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Tide apps will then have access to the &lt;code&gt;bark&lt;&#x2F;code&gt; method on &lt;code&gt;Request&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;async_std&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Result&amp;lt;(), std::io::Error&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; app = tide::new();
&lt;&#x2F;span&gt;&lt;span&gt;    app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;req&lt;&#x2F;span&gt;&lt;span&gt;| async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{ req.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;bark&lt;&#x2F;span&gt;&lt;span&gt;() });
&lt;&#x2F;span&gt;&lt;span&gt;    app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;listen&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;what-s-next&quot;&gt;What&#x27;s next?&lt;&#x2F;h2&gt;
&lt;p&gt;As you can tell from our JSON example, error handling isn&#x27;t &lt;em&gt;great&lt;&#x2F;em&gt; yet. The
error types don&#x27;t align the way we want them to, and that&#x27;s a bit of an issue.
Removing the &lt;code&gt;unwrap&lt;&#x2F;code&gt;s required to make Tide function properly is high on our
list.&lt;&#x2F;p&gt;
&lt;p&gt;But after that we&#x27;d like to focus on expanding the set of features. There are a
lot of things people want to do with web apps, and we&#x27;d like to learn what they
are. In particular WebSockets is something we&#x27;ve heard come up regularly. But so
is enabling good HTTP security out of the box.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s still the early days for Tide, and we&#x27;re excited for what folks will be
building. We&#x27;d love to hear about your experiences using Tide. The better we
understand what people are doing, the better we can make Tide a tool that helps
folks succeed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve covered the future and present of Tide, and covered its
architecture and design philosophy. It probably bears repeating that our 0.4.0
release hardly reflects a &lt;em&gt;done&lt;&#x2F;em&gt; state. Instead it&#x27;s the first step into a new
direction for the project. We&#x27;re very excited for the future of Rust, and in
particular async networking.&lt;&#x2F;p&gt;
&lt;p&gt;We believe Tide poses an interesting direction for writing HTTP servers; one
that blends familiarity from other languages with Rust&#x27;s unique way of doing
things, resulting in something that&#x27;s more than the sum of its parts. Either
way; we&#x27;re excited to be sharing this with y&#x27;all. And with that I&#x27;m going on
vacation -- back on the 11th of December. We hope you enjoy &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tide&#x2F;0.4.0&#x2F;tide&#x2F;&quot;&gt;Tide
0.4&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;Thanks to Friedel Ziegelmayer, Felipe Sere, Tirr-c, Nemo157, Oli Obk, David
Tolnay, and countless others for their help and assistance with this post,
issues, bug fixes, designs, and all the other work that goes into making a
release. Tide wouldn&#x27;t have been possible without everyone who has been
involved.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Error Handling Survey</title>
            <pubDate>Wed, 13 Nov 2019 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/error-handling-survey/</link>
            <guid>https://blog.yoshuawuyts.com/error-handling-survey/</guid>
            <description>&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;Rust&#x27;s error handling is a pleasure to use thanks to the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;fmt&#x2F;type.Result.html&quot;&gt;&lt;code&gt;Result&lt;&#x2F;code&gt; type&lt;&#x2F;a&gt;. It
ensures Rust&#x27;s error handling is always &lt;em&gt;correct&lt;&#x2F;em&gt;, &lt;em&gt;visible&lt;&#x2F;em&gt;, and &lt;em&gt;performant&lt;&#x2F;em&gt;.
And with the addition of the &lt;code&gt;?&lt;&#x2F;code&gt; operator in &lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;2016&#x2F;11&#x2F;10&#x2F;Rust-1.13.html&quot;&gt;Rust 1.13&lt;&#x2F;a&gt;, and the
addition of return types from main in &lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;2018&#x2F;05&#x2F;10&#x2F;Rust-1.26.html#main-can-return-a-result&quot;&gt;Rust 1.26&lt;&#x2F;a&gt; Rust&#x27;s error handling has only
kept improving.&lt;&#x2F;p&gt;
&lt;p&gt;However it seems we haven&#x27;t quite reached the end of the road yet. The Crates.io
ecosystem has seen a recent addition of a fair number of error-oriented
libraries that try and improve upon the status quo of Rust&#x27;s error handling.&lt;&#x2F;p&gt;
&lt;p&gt;This post is a survey of the current crates.io error library landscape.
&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#opinions&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;opinions&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;This is not to say I don&#x27;t have any preferences in terms of error
handling, but I think presenting an overview of error handling in userland is
more &lt;em&gt;valuable&lt;&#x2F;em&gt;. Any progress on this topic from the Rust teams will first
understanding of which problems currently exist with error handling and how
they&#x27;re already being solved.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;libraries&quot;&gt;Libraries&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;error-chain&quot;&gt;error-chain&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;error-chain&#x2F;0.12.1&#x2F;error_chain&#x2F;&quot;&gt;error-chain&lt;&#x2F;a&gt; is one of the earlier error handling libraries and was released in
&lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;error-chain&#x2F;versions&quot;&gt;April of 2016&lt;&#x2F;a&gt;. A lot of what&#x27;s proposed in this library has become part of std
over the years. In particular it introduced the following features:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The concept of &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;error-chain&#x2F;0.12.1&#x2F;error_chain&#x2F;#chaining-errors&quot;&gt;&quot;chaining&quot; errors&lt;&#x2F;a&gt; to propagate error causes.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;error-chain&#x2F;0.12.1&#x2F;error_chain&#x2F;struct.Backtrace.html&quot;&gt;backtraces&lt;&#x2F;a&gt; that capture the stack at the point of error creation.&lt;&#x2F;li&gt;
&lt;li&gt;A way to create new errors through the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;error-chain&#x2F;0.12.1&#x2F;error_chain&#x2F;#linking-errors&quot;&gt;&lt;code&gt;error_chain!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; macro.&lt;&#x2F;li&gt;
&lt;li&gt;A &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;error-chain&#x2F;0.12.1&#x2F;error_chain&#x2F;macro.bail.html&quot;&gt;&lt;code&gt;bail!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; macro to create new errors.&lt;&#x2F;li&gt;
&lt;li&gt;An &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;error-chain&#x2F;0.12.1&#x2F;error_chain&#x2F;macro.ensure.html&quot;&gt;&lt;code&gt;ensure!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; macro to create error-based assertions. &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#error-assertions&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;li&gt;
&lt;li&gt;A &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;error-chain&#x2F;0.12.1&#x2F;error_chain&#x2F;macro.quick_main.html&quot;&gt;&lt;code&gt;quick_main!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; macro to allow returning &lt;code&gt;Result&lt;&#x2F;code&gt; from &lt;code&gt;main&lt;&#x2F;code&gt; with an &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;error-chain&#x2F;0.12.1&#x2F;error_chain&#x2F;trait.ExitCode.html&quot;&gt;&lt;code&gt;ExitCode&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Fallible main function.
&lt;&#x2F;span&gt;&lt;span&gt;quick_main!(|| -&amp;gt; Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Chain errors to provide context.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res: Result&amp;lt;()&amp;gt; = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;do_something&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;chain_err&lt;&#x2F;span&gt;&lt;span&gt;(|| &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;something went wrong&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Error-based assertions.
&lt;&#x2F;span&gt;&lt;span&gt;    ensure!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;num too big&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Return ad-hoc errors from strings.
&lt;&#x2F;span&gt;&lt;span&gt;    bail!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Looking at this library it&#x27;s quite obvious it&#x27;s aged a bit. But in a good way;
because many of its innovations have become part of everyday error handling in
Rust, and the need for the library has lessened.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;error-assertions&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;These are assertions that instead of panicking return a
&lt;code&gt;Result::Err&lt;&#x2F;code&gt;. For example &lt;code&gt;ensure!(list.len() &amp;lt; 12, &quot;list is too long&quot;)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;failure&quot;&gt;failure&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;failure&quot;&gt;Failure&lt;&#x2F;a&gt; is the spiritual successor to &lt;code&gt;error-chain&lt;&#x2F;code&gt;, and was released in
&lt;a href=&quot;https:&#x2F;&#x2F;boats.gitlab.io&#x2F;blog&#x2F;post&#x2F;2017-11-16-announcing-failure&#x2F;&quot;&gt;November of 2017&lt;&#x2F;a&gt;. It comes with an analysis of the limitations of the error
trait, and introduced a new trait, &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;failure&#x2F;0.1.6&#x2F;failure&#x2F;trait.Fail.html&quot;&gt;&lt;code&gt;Fail&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, that served as a prototype of how
to overcome those limitations. In particular it came with the following
features:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A way to create new errors from strings through &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;failure&#x2F;0.1.1&#x2F;failure&#x2F;macro.format_err.html&quot;&gt;&lt;code&gt;format_err!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;A way to exit from functions early through &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;error-chain&#x2F;0.12.1&#x2F;error_chain&#x2F;macro.bail.html&quot;&gt;&lt;code&gt;bail!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;A way to perform error-based assertions through &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;error-chain&#x2F;0.12.1&#x2F;error_chain&#x2F;macro.ensure.html&quot;&gt;&lt;code&gt;ensure!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Support for backtraces through &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;failure&#x2F;0.1.1&#x2F;failure&#x2F;struct.backtrace.html&quot;&gt;&lt;code&gt;Backtrace&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;A way to propagate error causes through &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;failure&#x2F;0.1.1&#x2F;failure&#x2F;struct.context.html&quot;&gt;&lt;code&gt;Context&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;failure&#x2F;0.1.1&#x2F;failure&#x2F;struct.causes.html&quot;&gt;&lt;code&gt;Causes&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;failure&#x2F;0.1.1&#x2F;failure&#x2F;trait.ResultExt.html&quot;&gt;&lt;code&gt;ResultExt&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;An easier way to use dynamic boxed errors through &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;failure&#x2F;0.1.1&#x2F;failure&#x2F;struct.error.html&quot;&gt;&lt;code&gt;Error&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Defining custom errors through [&lt;code&gt;#[derive(Fail)]&lt;&#x2F;code&gt;] and the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;failure&#x2F;0.1.6&#x2F;failure&#x2F;trait.Fail.html&quot;&gt;&lt;code&gt;Fail&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; trait.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;boats.gitlab.io&#x2F;failure&#x2F;error-errorkind.html&quot;&gt;Extensive documentation&lt;&#x2F;a&gt; on how to create your own stdlib-like errors.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! A basic example of failure at work.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;failure::{ensure, Error, ResultExt};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;check&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;num&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Result&amp;lt;(), Error&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    ensure!(num &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;number exceeded threshold&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Result&amp;lt;(), Error&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;check&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Checking number failed.&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;check&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Checking number failed.&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It seems as &lt;code&gt;failure&lt;&#x2F;code&gt; was designed in anticipation of &lt;code&gt;main&lt;&#x2F;code&gt; being able to
return &lt;code&gt;Result&lt;&#x2F;code&gt;, and so unlike &lt;code&gt;error-chain&lt;&#x2F;code&gt; it doesn&#x27;t bother with that. Also
it brings back the ability to define an [&lt;code&gt;Error&lt;&#x2F;code&gt; + &lt;code&gt;ErrorKind&lt;&#x2F;code&gt;]. It feels like
the library was equal parts trying to improve defining new errors for use in
libraries, as ad-hoc errors for use in applications.&lt;&#x2F;p&gt;
&lt;p&gt;[&lt;code&gt;#[derive(Fail)]&lt;&#x2F;code&gt;]: https:&#x2F;&#x2F;docs.rs&#x2F;failure_derive&#x2F;0.1.5&#x2F;failure_derive&#x2F;derive.Fail.html&lt;&#x2F;p&gt;
&lt;h3 id=&quot;context-attribute&quot;&gt;context-attribute&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;context-attribute&quot;&gt;context-attribute&lt;&#x2F;a&gt; was a library that I
wrote in May of 2019 to solve the locality problem of &lt;code&gt;failure&lt;&#x2F;code&gt;&#x27;s
&lt;code&gt;ResultExt::context&lt;&#x2F;code&gt; method.&lt;&#x2F;p&gt;
&lt;p&gt;Namely when you&#x27;re applying &lt;code&gt;.context&lt;&#x2F;code&gt; onto a function, what you&#x27;re really doing
is describing what that function does. This is so that when an error occurs from
that function, we&#x27;re provided with human-readable &lt;em&gt;context&lt;&#x2F;em&gt; of what we were
trying to do. But instead of that context being provided by the function we&#x27;re
calling, the context needs to be set by the &lt;em&gt;caller&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Not only does it feel like the context and the error site are detached when
using &lt;code&gt;.context()&lt;&#x2F;code&gt;, it makes the calling code harder to read because of all the
inline documentation strings.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Error context being provided at call site.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;square&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;num&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;, failure::Error&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    ensure!(num &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Number was too large&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(num * num)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Result&amp;lt;(), failure::Error&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;square&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Squaring a number failed&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;square&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10 &lt;&#x2F;span&gt;&lt;span&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Squaring a number failed&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Error context being provided during definition.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Square a number if it&amp;#39;s less than 10.
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;square&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;num&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;, failure::Error&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    ensure!(num &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Number was too large&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(num * num)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Result&amp;lt;(), failure::Error&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;square&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;square&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10 &lt;&#x2F;span&gt;&lt;span&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;)?;
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;err-derive&quot;&gt;err-derive&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;err-derive&#x2F;0.1.6&#x2F;err_derive&#x2F;&quot;&gt;err-derive&lt;&#x2F;a&gt; is a &lt;code&gt;failure&lt;&#x2F;code&gt;-like derive macro for
&lt;code&gt;std::error::Error&lt;&#x2F;code&gt; first released in December of 2018. It&#x27;s motivation for
existing is that since &lt;code&gt;std::error::Error&lt;&#x2F;code&gt; is going to be gaining many of the
benefits of &lt;code&gt;failure::Fail&lt;&#x2F;code&gt;, there should be a macro to use just that.&lt;&#x2F;p&gt;
&lt;p&gt;Features it provides are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Defining custom errors through [&lt;code&gt;#[derive(Error)]&lt;&#x2F;code&gt;].&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;[&lt;code&gt;#[derive(Error)]&lt;&#x2F;code&gt;]: https:&#x2F;&#x2F;docs.rs&#x2F;err-derive&#x2F;0.1.6&#x2F;err_derive&#x2F;derive.Error.html&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Error-derive in action.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::error::Error;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Debug, derive_error::Error)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub enum &lt;&#x2F;span&gt;&lt;span&gt;LoadingError {
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;(display = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;could not decode file&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)]
&lt;&#x2F;span&gt;&lt;span&gt;    FormatError(#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;(cause)] FormatError),
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;(display = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;could not find file: {:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, path)]
&lt;&#x2F;span&gt;&lt;span&gt;    NotFound { path: PathBuf },
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;print_error&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;e&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;dyn Error) {
&lt;&#x2F;span&gt;&lt;span&gt;    eprintln!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;error: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, e);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; cause = e.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;source&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(e) = cause {
&lt;&#x2F;span&gt;&lt;span&gt;        eprintln!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;caused by: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, e);
&lt;&#x2F;span&gt;&lt;span&gt;        cause = e.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;source&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;auto-enums&quot;&gt;auto_enums&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;auto_enums&#x2F;0.7.1&#x2F;auto_enums&#x2F;index.html&quot;&gt;auto-enums&lt;&#x2F;a&gt; is a proc macro prototype of a language feature to enable more
flexible &lt;code&gt;impl Trait&lt;&#x2F;code&gt; return types. But since &lt;code&gt;Error&lt;&#x2F;code&gt; is a trait, it&#x27;s uses
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;taiki-e&#x2F;auto_enums&#x2F;blob&#x2F;master&#x2F;docs&#x2F;supported_traits&#x2F;std&#x2F;error.md&quot;&gt;extend to error handling
too&lt;&#x2F;a&gt;.
It was first released in December of 2018.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;auto-enums&lt;&#x2F;code&gt; unfortunately doesn&#x27;t allow anonymous &lt;code&gt;impl Error&lt;&#x2F;code&gt; yet inside
&lt;code&gt;Result&lt;&#x2F;code&gt;, but it &lt;em&gt;can&lt;&#x2F;em&gt; create an auto-derive for &lt;code&gt;Error&lt;&#x2F;code&gt; if all variants&#x27; inner
values in an enum implement &lt;code&gt;Error&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Quickly create a new error type that&amp;#39;s the sum of several other error types.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;auto_enums::enum_derive;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::io;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;enum_derive&lt;&#x2F;span&gt;&lt;span&gt;(Error)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;Error {
&lt;&#x2F;span&gt;&lt;span&gt;    Io(std::io::Error),
&lt;&#x2F;span&gt;&lt;span&gt;    Fmt(std::fmt::Error),
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Result&amp;lt;(), Error&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; err = io::Error::new(io::ErrorKind::Other, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;oh no&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    Err(Error::Io(err))
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Result&amp;lt;(), Error&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span&gt;()?;
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Hello, world!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But presumably if &lt;code&gt;impl Trait&lt;&#x2F;code&gt; in &lt;code&gt;auto_enums&lt;&#x2F;code&gt; would work for &lt;code&gt;Error&lt;&#x2F;code&gt; the way it
does for other traits, the error enum would be anonymous and created on the fly.
Which would allow us to do multiple operations with different error types in a
single function without declaring a new error type.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::error::Error;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::fs;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Result&amp;lt;(), impl Error&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; num = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i8&lt;&#x2F;span&gt;&lt;span&gt;::from_str_radix(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;)?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; file = fs::read_to_string(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;.&#x2F;README.md&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;snafu&quot;&gt;snafu&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;snafu&quot;&gt;snafu&lt;&#x2F;a&gt; is an error handling library first released in January 2019. The purpose
of it is: &quot;to easily assign underlying errors into domain-specific errors
while adding context&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;It seems to draw from experiences of using &lt;code&gt;failure&lt;&#x2F;code&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;snafu&#x2F;0.6.0&#x2F;snafu&#x2F;guide&#x2F;comparison&#x2F;failure&#x2F;index.html&quot;&gt;ships a comparison&lt;&#x2F;a&gt;
as part of the provided documentation. A primary difference seem to be that
&lt;code&gt;failure&lt;&#x2F;code&gt; defines a new trait &lt;code&gt;Fail&lt;&#x2F;code&gt;, while &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;snafu&#x2F;0.6.0&#x2F;snafu&#x2F;guide&#x2F;comparison&#x2F;failure&#x2F;index.html#a-custom-fail-type-and-using-the-error-type&quot;&gt;&lt;code&gt;snafu&lt;&#x2F;code&gt; uses &lt;code&gt;std::error::Error&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
Snafu also don&#x27;t thinks having shorthands to create errors from strings is very
important, stating: &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;snafu&#x2F;0.6.0&#x2F;snafu&#x2F;guide&#x2F;comparison&#x2F;failure&#x2F;index.html#strings-as-errors&quot;&gt;&quot;It&#x27;s unclear what benefit Failure provides
here.&quot;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Snafu provides the following features:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A way to perform error-based assertions through &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;snafu&#x2F;0.6.0&#x2F;snafu&#x2F;macro.ensure.html&quot;&gt;&lt;code&gt;ensure!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Support for backtraces through &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;snafu&#x2F;0.6.0&#x2F;snafu&#x2F;struct.Backtrace.html&quot;&gt;&lt;code&gt;Backtrace&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;A way to propagate error causes through &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;snafu&#x2F;0.6.0&#x2F;snafu&#x2F;trait.ResultExt.html&quot;&gt;&lt;code&gt;ResultExt&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;and [&lt;code&gt;OptionExt&lt;&#x2F;code&gt;].&lt;&#x2F;li&gt;
&lt;li&gt;Defining custom errors through [&lt;code&gt;#[derive(Snafu)]&lt;&#x2F;code&gt;].&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;snafu&#x2F;0.6.0&#x2F;snafu&#x2F;guide&#x2F;index.html&quot;&gt;Extensive documentation&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; A small taste of defining &amp;amp; using errors with snafu.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Debug, Snafu)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;Error {
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;snafu&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;display&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Could not open config from {}: {}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, filename.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;display&lt;&#x2F;span&gt;&lt;span&gt;(), source))]
&lt;&#x2F;span&gt;&lt;span&gt;    OpenConfig {
&lt;&#x2F;span&gt;&lt;span&gt;        filename: PathBuf,
&lt;&#x2F;span&gt;&lt;span&gt;        source: std::io::Error,
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;snafu&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;display&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;The user id {} is invalid&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, user_id))]
&lt;&#x2F;span&gt;&lt;span&gt;    UserIdInvalid { user_id: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;, backtrace: Backtrace },
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;log_in_user &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;filename&lt;&#x2F;span&gt;&lt;span&gt;: Path, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt;, std::error::Error&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; config = fs::read(filename).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span&gt;(Error::OpenConfig { filename })?;
&lt;&#x2F;span&gt;&lt;span&gt;    ensure!(id == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;42&lt;&#x2F;span&gt;&lt;span&gt;, Error::UserIdInvalid { user_id });
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;[&lt;code&gt;#[derive(Snafu)]&lt;&#x2F;code&gt;]: https:&#x2F;&#x2F;docs.rs&#x2F;snafu&#x2F;0.6.0&#x2F;snafu&#x2F;derive.Snafu.html
[&lt;code&gt;OptionExt&lt;&#x2F;code&gt;]: https:&#x2F;&#x2F;docs.rs&#x2F;snafu&#x2F;0.6.0&#x2F;snafu&#x2F;trait.OptionExt.html&lt;&#x2F;p&gt;
&lt;h3 id=&quot;fehler&quot;&gt;fehler&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;fehler&quot;&gt;fehler&lt;&#x2F;a&gt; is a new error library by the inimitable Boats,
released in September of 2019 (the same author as &lt;code&gt;failure&lt;&#x2F;code&gt;). It feels like an
experimental attempt to answer the question of: &quot;What if we introduced checked
exception syntactic sugar for Rust&#x27;s error handling&quot;. It seems to propose that
what &lt;code&gt;async&#x2F;.await&lt;&#x2F;code&gt; is to &lt;code&gt;Future&lt;&#x2F;code&gt;, &lt;code&gt;throw&#x2F;throws&lt;&#x2F;code&gt; would be to &lt;code&gt;Result&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This library was only released after the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;backtrace&#x2F;index.html&quot;&gt;&lt;code&gt;backtrace&lt;&#x2F;code&gt;
feature&lt;&#x2F;a&gt; landed on nightly,
and
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;error&#x2F;trait.Error.html#method.source&quot;&gt;&lt;code&gt;Error::source&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
landed in &lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;2018&#x2F;10&#x2F;25&#x2F;Rust-1.30.0.html&quot;&gt;Rust 1.30&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The innovation it provides here is the removal of the need to &lt;code&gt;Ok&lt;&#x2F;code&gt; wrap each
value at the end of a statement. Meaning &lt;code&gt;Ok(())&lt;&#x2F;code&gt; is no longer needed.
Additionally creating new errors can be done using the &lt;code&gt;error!&lt;&#x2F;code&gt; macro. And
returning errors from the function (&quot;throwing&quot;) errors can done using the
&lt;code&gt;throw!&lt;&#x2F;code&gt; macro.&lt;&#x2F;p&gt;
&lt;p&gt;Each function is annotated using the &lt;code&gt;fehler::throws&lt;&#x2F;code&gt; attribute. It optionally
takes an argument for the error type, such as &lt;code&gt;io::Error&lt;&#x2F;code&gt;. If the error type is
omitted, it assumes &lt;code&gt;Box&amp;lt;dyn Error + Send + Sync + &#x27;static&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;edit: the following section is slightly out of date as fehler merged a radical
simplification to their API &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;withoutboats&#x2F;fehler&#x2F;pull&#x2F;26&quot;&gt;4 hours
ago&lt;&#x2F;a&gt;. It now only exposes
&lt;code&gt;throw&lt;&#x2F;code&gt; and &lt;code&gt;throws&lt;&#x2F;code&gt;, and allow specifying your own default error type.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Unlike &lt;code&gt;failure&lt;&#x2F;code&gt;, this library only defines methods for propagating errors and
creating string errors. It doesn&#x27;t have any of the extra error-definition
utilities &lt;code&gt;failure&lt;&#x2F;code&gt; had. In particular it provides:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Creating new errors from Strings through &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;fehler&#x2F;1.0.0-alpha.1&#x2F;fehler&#x2F;macro.error.html&quot;&gt;&lt;code&gt;error!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Returning errors from functions using &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;fehler&#x2F;1.0.0-alpha.1&#x2F;fehler&#x2F;macro.throw.html&quot;&gt;&lt;code&gt;throw!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Removing the need to write &lt;code&gt;Result&lt;&#x2F;code&gt; in the function signature, Ok-wrapping,
and dynamic errors through &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;fehler&#x2F;1.0.0-alpha.1&#x2F;fehler&#x2F;attr.throws.html&quot;&gt;&lt;code&gt;throws!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;A way to propagate error causes through &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;fehler&#x2F;1.0.0-alpha.1&#x2F;fehler&#x2F;trait.Context.html&quot;&gt;&lt;code&gt;Context&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Printing a list of error causes when returned from &lt;code&gt;main&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Error handling relying only on stdlib
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::error::Error;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;square&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;, Box&amp;lt;dyn Error + Send + Sync + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; x &amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        Err(format!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Number is too large&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;))?;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(x * x)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! An example of Fehler in use.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;fehler::{throws, throw, error};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;throws&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;square&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; x &amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        throw!(error!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Number is too large&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;));
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    x * x
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! If Fehler&amp;#39;s proc macros were directly implemented as lang features.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;square&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt; throws {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; x &amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;12 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        throw &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Number is too large&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    x * x
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;anyhow&quot;&gt;anyhow&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;anyhow&quot;&gt;anyhow&lt;&#x2F;a&gt; is an error-handling library for applications,
and was first released on October 7th, 2019. It was built to make it easier to
propagate errors in applications, much like Fehler. But instead of prototyping
new language features, it defines a few new types and traits; with zero
dependencies. Its tag line is: &quot;A better &lt;code&gt;Box&amp;lt;dyn Error&amp;gt;&lt;&#x2F;code&gt;&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;This library was only possible after the implementation of &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;pull&#x2F;2504&quot;&gt;&lt;code&gt;RFC 2504&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; landed, and it requires Rust
1.34+ in order to function. The main features it provides are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Dynamic errors through &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;anyhow&#x2F;1.0.21&#x2F;anyhow&#x2F;struct.Error.html&quot;&gt;&lt;code&gt;Error&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Conveniently iterating over
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;error&#x2F;trait.Error.html#method.source&quot;&gt;causes&lt;&#x2F;a&gt;
through &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;anyhow&#x2F;1.0.21&#x2F;anyhow&#x2F;struct.Chain.html&quot;&gt;&lt;code&gt;Chain&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Creating new errors from strings through &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;anyhow&#x2F;1.0.21&#x2F;anyhow&#x2F;macro.anyhow.html&quot;&gt;&lt;code&gt;anyhow!&lt;&#x2F;code&gt; &#x2F;
&lt;code&gt;format_err!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Returning from functions early with new errors through &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;anyhow&#x2F;1.0.21&#x2F;anyhow&#x2F;macro.bail.html&quot;&gt;&lt;code&gt;bail!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Error-based assertions through &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;anyhow&#x2F;1.0.21&#x2F;anyhow&#x2F;macro.ensure.html&quot;&gt;&lt;code&gt;ensure!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;The ability to extend &lt;code&gt;Result&lt;&#x2F;code&gt; with &lt;code&gt;context&lt;&#x2F;code&gt; through &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;anyhow&#x2F;1.0.21&#x2F;anyhow&#x2F;trait.Context.html&quot;&gt;&lt;code&gt;Context&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;A shorthand type &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;anyhow&#x2F;1.0.21&#x2F;anyhow&#x2F;type.Result.html&quot;&gt;&lt;code&gt;Result&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; for &lt;code&gt;Result&amp;lt;T, anyhow::Error&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Printing a list of error causes when returned from &lt;code&gt;main&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! An example using anyhow.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;anyhow::{Context, Result};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    ...
&lt;&#x2F;span&gt;&lt;span&gt;    it.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;detach&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Failed to detach the important thing&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; content = std::fs::read(path)
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;with_context&lt;&#x2F;span&gt;&lt;span&gt;(|| format!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Failed to read instrs from &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, path))?;
&lt;&#x2F;span&gt;&lt;span&gt;    ...
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;thiserror&quot;&gt;thiserror&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;thiserror&quot;&gt;thiserror&lt;&#x2F;a&gt; was written by the same author,
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dtolnay&#x2F;&quot;&gt;dtolnay&lt;&#x2F;a&gt;, and released in the same week as
&lt;code&gt;anyhow&lt;&#x2F;code&gt;. Where both &lt;code&gt;fehler&lt;&#x2F;code&gt; and &lt;code&gt;anyhow&lt;&#x2F;code&gt; cover dynamic errors, &lt;code&gt;thiserror&lt;&#x2F;code&gt; is
focused on creating structured errors.&lt;&#x2F;p&gt;
&lt;p&gt;In a way, &lt;code&gt;anyhow&lt;&#x2F;code&gt; and &lt;code&gt;thiserror&lt;&#x2F;code&gt; feel like they have taken the wide ranger of
features &lt;code&gt;failure&lt;&#x2F;code&gt; introduced in 2017, and split the domain between them.
&lt;code&gt;thiserror&lt;&#x2F;code&gt; only contains a single trait to define new errors through:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Create new errors through &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;thiserror&#x2F;1.0.5&#x2F;thiserror&#x2F;derive.Error.html&quot;&gt;&lt;code&gt;#[derive(Error)]&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;thiserror::Error;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Error, Debug)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub enum &lt;&#x2F;span&gt;&lt;span&gt;DataStoreError {
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;data store disconnected&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)]
&lt;&#x2F;span&gt;&lt;span&gt;    Disconnect(#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;] io::Error),
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;the data for key `{0}` is not available&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)]
&lt;&#x2F;span&gt;&lt;span&gt;    Redaction(String),
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;invalid header (expected {expected:?}, found {found:?})&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)]
&lt;&#x2F;span&gt;&lt;span&gt;    InvalidHeader {
&lt;&#x2F;span&gt;&lt;span&gt;        expected: String,
&lt;&#x2F;span&gt;&lt;span&gt;        found: String,
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;unknown data store error&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)]
&lt;&#x2F;span&gt;&lt;span&gt;    Unknown,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;thiserror&lt;&#x2F;code&gt;&#x27;s derive formatting was fairly unique at the time of release, and
has since been extracted into the
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yaahc&#x2F;displaydoc&quot;&gt;displaydoc&lt;&#x2F;a&gt; crate to implement
&lt;code&gt;#[derive(Display)]&lt;&#x2F;code&gt; for structs and enums.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;std-error-error&quot;&gt;std::error::Error&lt;&#x2F;h3&gt;
&lt;p&gt;And last but not least, &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;error&#x2F;trait.Error.html&quot;&gt;std&#x27;s Error
trait&lt;&#x2F;a&gt; has come a long way
since the early days. A notable few changes have happened over the past few
years:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Error::description&lt;&#x2F;code&gt; was soft-deprecated in favor of &lt;code&gt;impl Display&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Error::cause&lt;&#x2F;code&gt; has been deprecated in favor of &lt;code&gt;Error::source&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Error::iter_chain&lt;&#x2F;code&gt; and &lt;code&gt;Error::iter_sources&lt;&#x2F;code&gt; are now available on nightly.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Error::backtrace&lt;&#x2F;code&gt; and the &lt;code&gt;backtrace&lt;&#x2F;code&gt; module are now available on nightly.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In addition with &lt;code&gt;Result&lt;&#x2F;code&gt; from main, exit codes, and the &lt;code&gt;?&lt;&#x2F;code&gt; operator we&#x27;ve
definitely come a long way from the early days of Rust&#x27;s error handling.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;features&quot;&gt;Features&lt;&#x2F;h2&gt;
&lt;p&gt;So far we&#x27;ve taken a look at 9 different error handling libraries, and you might
have noticed that they have a lot in common. In this section we&#x27;ll try and break
down which features libraries introduce, and what their differences are.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;returning-result-from-main&quot;&gt;Returning Result from main&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;error-chain&lt;&#x2F;code&gt; introduces the ability to return &lt;code&gt;Result&lt;&#x2F;code&gt; from main, and this was
added to Rust in &lt;code&gt;1.26&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;error-based-assertions&quot;&gt;Error-based assertions&lt;&#x2F;h3&gt;
&lt;p&gt;In the stdlib the &lt;code&gt;assert!&lt;&#x2F;code&gt; and &lt;code&gt;assert_eq!&lt;&#x2F;code&gt; macros exist. These are convenient
shorthands to check a condition, and panic if it doesn&#x27;t hold. However, it&#x27;s
quite common to check a condition, and want to return an error if it doesn&#x27;t
hold. To that extent &lt;code&gt;error-chain&lt;&#x2F;code&gt;, &lt;code&gt;failure&lt;&#x2F;code&gt;, &lt;code&gt;snafu&lt;&#x2F;code&gt;, and &lt;code&gt;anyhow&lt;&#x2F;code&gt; introduce a
new macro: &lt;code&gt;ensure!&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The largest difference between the macros is which values are valid in the
right-hand side of the macro. In &lt;code&gt;snafu&lt;&#x2F;code&gt; &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;snafu&#x2F;0.6.0&#x2F;snafu&#x2F;macro.ensure.html&quot;&gt;only structured
errors&lt;&#x2F;a&gt; are valid, in
&lt;code&gt;failure&lt;&#x2F;code&gt; &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;failure&#x2F;0.1.6&#x2F;src&#x2F;failure&#x2F;macros.rs.html#25-41&quot;&gt;only strings are
valid&lt;&#x2F;a&gt;, and in
&lt;code&gt;anyhow&lt;&#x2F;code&gt; &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;anyhow&#x2F;1.0.21&#x2F;anyhow&#x2F;macro.ensure.html&quot;&gt;both are
valid&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Strings in the right-hand side to create new, anonymous errors.
&lt;&#x2F;span&gt;&lt;span&gt;ensure!(user == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;only user 0 is allowed&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Structured errors in the right-hand side.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::io::{Error, ErrorKind}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;ensure!(depth &amp;lt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;MAX_DEPTH&lt;&#x2F;span&gt;&lt;span&gt;, Error::new(ErrorKind::Other, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;oh no&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;causes&quot;&gt;Causes&lt;&#x2F;h3&gt;
&lt;p&gt;Many libraries implement the ability to recursively iterate over
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;error&#x2F;trait.Error.html#method.source&quot;&gt;&lt;code&gt;Error::source&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
(formerly &lt;code&gt;Error::cause&lt;&#x2F;code&gt;). These libraries include &lt;code&gt;error-chain&lt;&#x2F;code&gt;, &lt;code&gt;failure&lt;&#x2F;code&gt;,
&lt;code&gt;fehler&lt;&#x2F;code&gt;, and &lt;code&gt;anyhow&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In addition, &lt;code&gt;fehler&lt;&#x2F;code&gt; and &lt;code&gt;anyhow&lt;&#x2F;code&gt; will print the list of causes when returned
from &lt;code&gt;fn main&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;Error: Failed to read instrs from .&#x2F;path&#x2F;to&#x2F;instrs.json
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Caused by:
&lt;&#x2F;span&gt;&lt;span&gt;    No such file or directory (os error 2)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;err-derive&lt;&#x2F;code&gt; doesn&#x27;t provide any facilities for this, but recommends &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;err-derive&#x2F;0.1.6&#x2F;err_derive&#x2F;#printing-the-error&quot;&gt;using a
pattern to print
errors&lt;&#x2F;a&gt;. This
could be used with other libraries such as &lt;code&gt;snafu&lt;&#x2F;code&gt; as well. But it misses the
&quot;print from main&quot; functionality of &lt;code&gt;fehler&lt;&#x2F;code&gt; and &lt;code&gt;anyhow&lt;&#x2F;code&gt;. And it doesn&#x27;t
provide the same convenience &lt;code&gt;anyhow::Chain&lt;&#x2F;code&gt; does either by implementing
&lt;code&gt;DoubleEndedIterator&lt;&#x2F;code&gt; and &lt;code&gt;ExactSizeIterator&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; cause in error.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;chain&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;error: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, cause)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;backtraces&quot;&gt;Backtraces&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;error-chain&lt;&#x2F;code&gt;, &lt;code&gt;failure&lt;&#x2F;code&gt;, and &lt;code&gt;snafu&lt;&#x2F;code&gt; add backtrace support to their error
types. Backtrace support is currently available on nightly, and &lt;code&gt;fehler&lt;&#x2F;code&gt;, and
&lt;code&gt;anyhow&lt;&#x2F;code&gt; make use of this. It seems that if this feature becomes available on
stable, backtrace support for errors will mostly have been covered.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;creating-errors-from-strings&quot;&gt;Creating errors from strings&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;failure&lt;&#x2F;code&gt;, and &lt;code&gt;anyhow&lt;&#x2F;code&gt; provide a &lt;code&gt;format_err!&lt;&#x2F;code&gt; macro that allows constructing
a boxed error from a string. &lt;code&gt;anyhow&lt;&#x2F;code&gt; has a type alias called &lt;code&gt;anyhow&lt;&#x2F;code&gt; with the
same functionality.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;fehler&lt;&#x2F;code&gt; provides a macro &lt;code&gt;error!&lt;&#x2F;code&gt; to similarly construct new errors from
strings.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; num = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;21&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;Err(format_err!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{} kitten paws&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, num));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;snafu&lt;&#x2F;code&gt; does not provide a dedicated macro for creating errors from strings, but
instead recommends using
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;snafu&#x2F;0.6.0&#x2F;snafu&#x2F;guide&#x2F;comparison&#x2F;failure&#x2F;index.html#strings-as-errors&quot;&gt;a pattern&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;example&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Result&amp;lt;(), Box&amp;lt;dyn std::error::Error&amp;gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    Err(format!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Something went bad: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;))?;
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;early-returns-with-string-errors&quot;&gt;Early returns with string errors&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;error-chain&lt;&#x2F;code&gt;, &lt;code&gt;failure&lt;&#x2F;code&gt;, and &lt;code&gt;anyhow&lt;&#x2F;code&gt; provide a &lt;code&gt;bail!&lt;&#x2F;code&gt; macro that allows
returning from a function early with an error constructed from a string.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;fehler&lt;&#x2F;code&gt; has a model where &lt;code&gt;Err&lt;&#x2F;code&gt; and &lt;code&gt;Ok&lt;&#x2F;code&gt; no longer are required, and provides
a &lt;code&gt;throw!&lt;&#x2F;code&gt; macro to return errors. And &lt;code&gt;error!&lt;&#x2F;code&gt; macro to create new errors from
strings.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;has_permission&lt;&#x2F;span&gt;&lt;span&gt;(user, resource) {
&lt;&#x2F;span&gt;&lt;span&gt;    bail!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;permission denied for accessing {}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, resource);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;snafu&lt;&#x2F;code&gt; does not provide a dedicated macro for creating errors from strings, but
instead recommends using the &lt;code&gt;Err(err)?&lt;&#x2F;code&gt; pattern.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;context-on-result&quot;&gt;Context on Result&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;failure&lt;&#x2F;code&gt;, &lt;code&gt;snafu&lt;&#x2F;code&gt;, &lt;code&gt;fehler&lt;&#x2F;code&gt;, and &lt;code&gt;anyhow&lt;&#x2F;code&gt; allow extending &lt;code&gt;Result&lt;&#x2F;code&gt; with
&lt;code&gt;context&lt;&#x2F;code&gt; method that wraps an error in a new error that provides a new entry
for &lt;code&gt;source&lt;&#x2F;code&gt;, effectively providing an extra layer of descriptions.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s unclear how each library goes about this, but especially &lt;code&gt;anyhow&lt;&#x2F;code&gt; seems to
have &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;anyhow&#x2F;1.0.21&#x2F;anyhow&#x2F;trait.Context.html#effect-on-downcasting&quot;&gt;gone to great
lengths&lt;&#x2F;a&gt;
to prevent it from interacting negatively with downcasting.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;do_it&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;helper&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Failed to complete the work&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ...
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;error-context&lt;&#x2F;code&gt; provides a way to move &lt;code&gt;.context&lt;&#x2F;code&gt; from the call site to the
error definition through doc comments.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Complete the work
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;helper&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ...
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;do_it&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;helper&lt;&#x2F;span&gt;&lt;span&gt;()?;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;custom-errors&quot;&gt;Custom errors&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;failure&lt;&#x2F;code&gt;, &lt;code&gt;err_derive&lt;&#x2F;code&gt;, &lt;code&gt;auto_enums&lt;&#x2F;code&gt;, &lt;code&gt;snafu&lt;&#x2F;code&gt;, and &lt;code&gt;thiserror&lt;&#x2F;code&gt; provide derives
to construct new errors. They each go about it slightly differently.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! Failure
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(failure::Fail, Debug)]
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fail&lt;&#x2F;span&gt;&lt;span&gt;(display = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Error code: {}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, code)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;RecordError {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;code&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! err_derive
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; `MyError::source` will return a reference to the `io_error` field
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Debug, err_derive::Error)]
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;(display = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;An error occurred.&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;MyError {
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;(cause)]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;io_error&lt;&#x2F;span&gt;&lt;span&gt;: io::Error,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! snafu
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Debug, Snafu)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;Error {
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;snafu&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;display&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Could not open config from {}: {}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, filename.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;display&lt;&#x2F;span&gt;&lt;span&gt;(), source))]
&lt;&#x2F;span&gt;&lt;span&gt;    OpenConfig {
&lt;&#x2F;span&gt;&lt;span&gt;        filename: PathBuf,
&lt;&#x2F;span&gt;&lt;span&gt;        source: std::io::Error,
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;snafu&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;display&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;The user id {} is invalid&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, user_id))]
&lt;&#x2F;span&gt;&lt;span&gt;    UserIdInvalid { user_id: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;, backtrace: Backtrace },
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;! thiserror
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(thiserror::Error, Debug)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub enum &lt;&#x2F;span&gt;&lt;span&gt;DataStoreError {
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;invalid header (expected {expected:?}, found {found:?})&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)]
&lt;&#x2F;span&gt;&lt;span&gt;    InvalidHeader {
&lt;&#x2F;span&gt;&lt;span&gt;        expected: String,
&lt;&#x2F;span&gt;&lt;span&gt;        found: String,
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;the data for key `{0}` is not available&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)]
&lt;&#x2F;span&gt;&lt;span&gt;    Redaction(String),
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;enum_derive&lt;&#x2F;span&gt;&lt;span&gt;(Error)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;Enum&amp;lt;A, B&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    A(A),
&lt;&#x2F;span&gt;&lt;span&gt;    B(B),
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;failure&lt;&#x2F;code&gt;, &lt;code&gt;err_derive&lt;&#x2F;code&gt;, and &lt;code&gt;snafu&lt;&#x2F;code&gt; all seem to make use of format-string like
interpolation inside inner attributes on structs to define custom error
messages. &lt;code&gt;thiserror&lt;&#x2F;code&gt; is different, and provides a more inline style of
formatting.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;auto_enums&lt;&#x2F;code&gt; is yet again different, in that it doesn&#x27;t provide the ability to
define new error messages, but will delegate to the error implementation of its
member&#x27;s inner values.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;other-miscellaneous&quot;&gt;Other &#x2F; Miscellaneous&lt;&#x2F;h2&gt;
&lt;p&gt;This is a list of miscellaneous developments around errors that seemed somewhat
related, and generally interesting.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;try-blocks&quot;&gt;Try blocks&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;try {}&lt;&#x2F;code&gt; blocks are an &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nightly&#x2F;unstable-book&#x2F;language-features&#x2F;try-blocks.html&quot;&gt;unstable
feature&lt;&#x2F;a&gt;
that introduces a new kind of block statement that can &quot;catch&quot; error propagation
using the &lt;code&gt;?&lt;&#x2F;code&gt; operator, and doesn&#x27;t require &lt;code&gt;Ok&lt;&#x2F;code&gt; wrapping at the end of the
block.&lt;&#x2F;p&gt;
&lt;p&gt;This is useful for when for example wanting to handle multiple errors in a
uniform way.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read_file&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;file&lt;&#x2F;span&gt;&lt;span&gt;: Path) -&amp;gt; io::Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; file = try {
&lt;&#x2F;span&gt;&lt;span&gt;        path.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_file&lt;&#x2F;span&gt;&lt;span&gt;().await?;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; file = fs::read_to_string(file).await?;
&lt;&#x2F;span&gt;&lt;span&gt;        file
&lt;&#x2F;span&gt;&lt;span&gt;    }.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;error reading the file&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;first 5 chars &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, file[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This feature seems to have some overlap with &lt;code&gt;fehler&lt;&#x2F;code&gt;&#x27;s &lt;code&gt;throw&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;throws&lt;&#x2F;code&gt;
syntax; and the interaction between the two language directions is definitely
interesting.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;verbose-io-errors&quot;&gt;Verbose IO errors&lt;&#x2F;h3&gt;
&lt;p&gt;When reading a file from a path fails, you&#x27;ll often see an error like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;Finished dev [unoptimized + debuginfo] target(s) in 0.56s
&lt;&#x2F;span&gt;&lt;span&gt;Running `target&#x2F;debug&#x2F;playground`
&lt;&#x2F;span&gt;&lt;span&gt;Error: Os { code: 2, kind: NotFound, message: &amp;quot;No such file or directory&amp;quot; }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is often quite unhelpful. &lt;em&gt;Which&lt;&#x2F;em&gt; file did we fail to read? What should we
do to make it pass? We can usually find out with a bit of debugging. But if the
error comes from a dependency, or a dependency&#x27;s dependency, figuring it out can
often become a huge chore.&lt;&#x2F;p&gt;
&lt;p&gt;In &lt;code&gt;async-std&lt;&#x2F;code&gt; we&#x27;re in the process of &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;async-rs&#x2F;async-std&#x2F;pull&#x2F;551&quot;&gt;adding &quot;verbose
errors&quot;&lt;&#x2F;a&gt; that contain this
information, and should reduce compilation times. Because it&#x27;s off the hot
path, and we already allocate regularly, it should hardly have any impact on
performance.&lt;&#x2F;p&gt;
&lt;p&gt;Returning verbose errors by default in the stdlib may not be the right fit. But
this is definitely something that has come up in the past, and will continue to
come up in the future unless it&#x27;s addressed. But as always, the hardest question
to answer is &lt;em&gt;how&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;error-pointer-registers&quot;&gt;Error pointer registers&lt;&#x2F;h3&gt;
&lt;p&gt;Apparently Swift has really efficient error handling using &lt;code&gt;try&#x2F;catch&lt;&#x2F;code&gt;. It
reserves &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;Gankra_&#x2F;status&#x2F;1175125334209024000&quot;&gt;a dedicated
register&lt;&#x2F;a&gt; for error
pointers, zeroes it, then checks if it&#x27;s still 0. The way it achieves this is
through a dedicated
&lt;a href=&quot;https:&#x2F;&#x2F;pbs.twimg.com&#x2F;media&#x2F;EE7jk7CXsAEiqDk?format=jpg&amp;amp;name=large&quot;&gt;&lt;code&gt;swifterror&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
instruction in LLVM.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s been mentioned that this is something that could be done for Rust&#x27;s &lt;code&gt;?&lt;&#x2F;code&gt; as
well, though nobody has the resources to.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;analysis&quot;&gt;Analysis&lt;&#x2F;h2&gt;
&lt;p&gt;It seems like &lt;code&gt;error-chain&lt;&#x2F;code&gt;, and &lt;code&gt;failure&lt;&#x2F;code&gt; marked some big upsets in error
handling for Rust. And since their release some of the value they&#x27;ve provided
has been merged back into the language. Since &lt;code&gt;error-chain&lt;&#x2F;code&gt; &lt;code&gt;Result&lt;&#x2F;code&gt; from &lt;code&gt;fn main&lt;&#x2F;code&gt; has become possible. And since &lt;code&gt;failure&lt;&#x2F;code&gt;, &lt;code&gt;Error::causes&lt;&#x2F;code&gt; has been
deprecated in favor of &lt;code&gt;Error::source&lt;&#x2F;code&gt;. And backtrace support has become
available on nightly.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;utilities&quot;&gt;Utilities&lt;&#x2F;h3&gt;
&lt;p&gt;However, throughout the years some features have been consistent among crates,
but never found their way into the standard library. In particular
&lt;code&gt;format_err!&lt;&#x2F;code&gt;, &lt;code&gt;ensure!&lt;&#x2F;code&gt;, and &lt;code&gt;bail!&lt;&#x2F;code&gt; are recurring in a lot of libraries, but
haven&#x27;t made their way in. Having more readily available methods of creating
and using string-based errors seems to be a desirable feature.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;creating-errors&quot;&gt;Creating errors&lt;&#x2F;h3&gt;
&lt;p&gt;Another common theme is the availability of a &lt;code&gt;context&lt;&#x2F;code&gt; method on &lt;code&gt;Result&lt;&#x2F;code&gt;.
There seems to be almost universal consensus among library authors that this is
desirable, yet it has no counterpart in stdlib yet.&lt;&#x2F;p&gt;
&lt;p&gt;From there it seems libraries can roughly be divided into two categories:
dynamic errors and structured errors. This split is best evidenced in the
sibling libraries of &lt;code&gt;anyhow&lt;&#x2F;code&gt;, and &lt;code&gt;thiserror&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In terms of dynamic error handling &lt;code&gt;failure&lt;&#x2F;code&gt;&#x27;s &lt;code&gt;Fail&lt;&#x2F;code&gt; type started the current
trend, and &lt;code&gt;fehler&lt;&#x2F;code&gt; and &lt;code&gt;anyhow&lt;&#x2F;code&gt; seem to have modernized it with what&#x27;s been
made available in stdlib since. In particular these libraries provide a better
version of &lt;code&gt;Box&amp;lt;dyn Error + Send + Sync + &#x27;static&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In terms of defining new errors, &lt;code&gt;snafu&lt;&#x2F;code&gt; and &lt;code&gt;thiserror&lt;&#x2F;code&gt; seem to have made the
most progress since &lt;code&gt;failure&lt;&#x2F;code&gt;. They mainly differ in the way serialization of
new errors works.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;language-developments&quot;&gt;Language developments&lt;&#x2F;h3&gt;
&lt;p&gt;In terms of language experimentations there have also been exciting
developments. &lt;code&gt;auto_enums&lt;&#x2F;code&gt; hypothesises that if &lt;code&gt;impl Trait&lt;&#x2F;code&gt; would work,
anonymous enums could be created for types that can delegate to their inner
implementations. And &lt;code&gt;fehler&lt;&#x2F;code&gt; proposes syntactic sugar to remove &lt;code&gt;Result&lt;&#x2F;code&gt; from
error use entirely, instead using checked exceptions through the &lt;code&gt;throw&lt;&#x2F;code&gt; and
&lt;code&gt;throws&lt;&#x2F;code&gt; keywords.&lt;&#x2F;p&gt;
&lt;p&gt;The similarities between &lt;code&gt;throw&lt;&#x2F;code&gt;, &lt;code&gt;throws&lt;&#x2F;code&gt;, and &lt;code&gt;try&lt;&#x2F;code&gt; could plausibly help lower
the barrier for learning Rust as they have much in common with mainstream
programming languages such as JavaScript, Swift, and Java. But ideally
further research would be conducted to help corroborate this.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve looked at 9 different error handling libraries, the features
they propose, and laid out how they compare to other libraries in order to
determine recurring themes.&lt;&#x2F;p&gt;
&lt;p&gt;There seems to be rough consensus in the ecosystem that we seem to need:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Some kind of replacement for &lt;code&gt;Box&amp;lt;dyn Error + Send + Sync + &#x27;static&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Some way of wrapping &lt;code&gt;Results&lt;&#x2F;code&gt; in &lt;code&gt;.context&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Some way to conveniently define new error types.&lt;&#x2F;li&gt;
&lt;li&gt;Some way to iterate over error causes (&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;58520&quot;&gt;#58520&lt;&#x2F;a&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Support for backtraces (&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;53487&quot;&gt;#53487&lt;&#x2F;a&gt;).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Additionally the functionality provided by &lt;code&gt;ensure!&lt;&#x2F;code&gt;, &lt;code&gt;bail!&lt;&#x2F;code&gt;, and &lt;code&gt;format_err!&lt;&#x2F;code&gt;
has been exported as part of many of the libraries, and seems to be along the
lines of: &quot;stable, popular, and small&quot; that is &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;withoutboats&#x2F;status&#x2F;1184797783921975296&quot;&gt;the bread and butter of
std&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Since starting work on this post, two others (&lt;a href=&quot;https:&#x2F;&#x2F;www.ncameron.org&#x2F;blog&#x2F;rust-in-2020-one-more-thing&#x2F;&quot;&gt;1&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;lukaskalbertodt.github.io&#x2F;2019&#x2F;11&#x2F;14&#x2F;thoughts-on-error-handling-in-rust.html&quot;&gt;2&lt;&#x2F;a&gt;) have written about error
handling. Which seems indicative error handling is something that&#x27;s on people&#x27;s
mind right now.&lt;&#x2F;p&gt;
&lt;p&gt;This is all I have to share on error handling at the moment. I hope this post
will be prove to be useful as people set out to improve Rust&#x27;s error handling.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Thanks to: Aleksey Kladov, Niko Matsakis, and Alex Crichton for reading
reviewing this post and helping refine it.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Runtime Diagnostics</title>
            <pubDate>Sun, 03 Nov 2019 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/runtime-diagnostics/</link>
            <guid>https://blog.yoshuawuyts.com/runtime-diagnostics/</guid>
            <description>&lt;p&gt;Rust is well-known for its helpful error messages, good tooling, and
generally &lt;em&gt;empathic&lt;&#x2F;em&gt; compiler interface. If something goes wrong, Rust tries
hard to help you get back on track.&lt;&#x2F;p&gt;
&lt;p&gt;In this post I&#x27;d like to talk about the runtime aspect of debugging errors.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;compiler-diagnostics&quot;&gt;Compiler Diagnostics&lt;&#x2F;h2&gt;
&lt;p&gt;The umbrella term for the messages the compiler prints during compilation is
&quot;diagnostics&quot;. When something goes wrong, the compiler has a lot of code in
place to try and identify what kind of error occurred, and if there&#x27;s perhaps a
suggestion available to help you fix it.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    printline!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello world!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;error: cannot find macro `printline!` in this scope
&lt;&#x2F;span&gt;&lt;span&gt; --&amp;gt; src&#x2F;main.rs:2:5
&lt;&#x2F;span&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;span&gt;2 |     printline!(&amp;quot;hello world!&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;  |     ^^^^^^^^^ help: a macro with a similar name exists: `println`
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;ekuber&quot;&gt;ekuber&lt;&#x2F;a&gt; once described it: in order to provide
helpful error messages, the compiler needs to understand a super set of the
language. That way when it rejects invalid code, it can still understand what
you were trying to do and guide you to the allowed subset.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;runtime-diagnostics&quot;&gt;Runtime Diagnostics&lt;&#x2F;h2&gt;
&lt;p&gt;During runtime the compiler no longer plays a role, and all error messages are
handled by the binary we&#x27;ve compiled. If a bug occurs in a Rust program during
Runtime, there several methods we can employ to figure out &lt;em&gt;why&lt;&#x2F;em&gt; the program
was rejected:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;RUST_BACKTRACE=1&lt;&#x2F;code&gt; can be passed during compilation to print stack traces when
the program panics.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;dbg!&lt;&#x2F;code&gt; is like &lt;code&gt;println!&lt;&#x2F;code&gt;, but includes line numbers, filenames, and is
convenient to write.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;gdb&lt;&#x2F;code&gt; and &lt;code&gt;rr&lt;&#x2F;code&gt; can be invoked on Rust programs to step through execution.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;bpftrace&lt;&#x2F;code&gt;, &lt;code&gt;dtrace&lt;&#x2F;code&gt;, and &lt;code&gt;perf&lt;&#x2F;code&gt; can be invoked on Rust programs.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;failure&lt;&#x2F;code&gt;, &lt;code&gt;fehler&lt;&#x2F;code&gt;, and &lt;code&gt;anyhow&lt;&#x2F;code&gt; provide &lt;code&gt;Context&lt;&#x2F;code&gt; error types that record
the flow of an error through the system.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Individual tools are often referred to as &quot;backtrace support&quot;, &quot;debugging&quot;, or
&quot;performance analysis&quot;. But I think these are all quite closely related, and
and it would make sense to group group them together under the umbrella of
&quot;runtime diagnostics&quot;. Because in the end all of these are similarly tools built
to help diagnose invalid code, and convert it to valid code. The only difference
is at which stage of development these tools are run.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;looking-ahead&quot;&gt;Looking Ahead&lt;&#x2F;h2&gt;
&lt;p&gt;If you consider Rust&#x27;s runtime diagnostics to be a single system, then there are
probably some things that could be improved. The first one being: figuring out
how to debug something often requires memorizing quite a few different tools.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;d be nice if &lt;code&gt;cargo run&lt;&#x2F;code&gt; integrated nicely with debuggers, so you could for
example do: &lt;code&gt;cargo run --debug&lt;&#x2F;code&gt; to spin up a debugger on a breakpoint. Or &lt;code&gt;cargo run --backtrace&lt;&#x2F;code&gt; to enable backtraces? Or what if we had rust&#x27;s diagnostics
printing available when something panics &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;athre0z&#x2F;color-backtrace&quot;&gt;as
well&lt;&#x2F;a&gt;?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    todo!();
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;thread &amp;#39;main&amp;#39; panicked at &amp;#39;todo!&amp;#39;, src&#x2F;main.rs:2:5
&lt;&#x2F;span&gt;&lt;span&gt; --&amp;gt; src&#x2F;main.rs:2:5
&lt;&#x2F;span&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;span&gt;2 |     todo!();
&lt;&#x2F;span&gt;&lt;span&gt;  |     ^^^^^^^^^ help: `fn main` has not yet been implemented
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or what about being able to detect and report deadlocks?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::sync::Mutex;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; data = Mutex::new(());
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; d1 = data.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; d2 = data.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;mutex deadlocked, src&#x2F;main.rs:6:5
&lt;&#x2F;span&gt;&lt;span&gt;  |
&lt;&#x2F;span&gt;&lt;span&gt;4 |     let data = Mutex::new(());
&lt;&#x2F;span&gt;&lt;span&gt;  |         ---- mutex was created here.
&lt;&#x2F;span&gt;&lt;span&gt;5 |     let d1 = data.lock();
&lt;&#x2F;span&gt;&lt;span&gt;  |         -- lock was first acquired here
&lt;&#x2F;span&gt;&lt;span&gt;6 |     let d2 = data.lock();
&lt;&#x2F;span&gt;&lt;span&gt;  |         ^^ lock could not be acquired here
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are a whole range of tools we may want to apply, from
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;miri&quot;&gt;miri&lt;&#x2F;a&gt; to &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;moarbugs&#x2F;status&#x2F;1188871733475864576&quot;&gt;thread-safety
sanitizers&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I think it would be fantastic if we could treat all of these systems as a
cohesive set of runtime diagnostics, that form a counterpart to Rust&#x27;s already
excellent compile diagnostics.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve looked at compile diagnostics, discussed what runtime
diagnostics are, and looked at possible future directions.&lt;&#x2F;p&gt;
&lt;p&gt;This post is not so much intended to present any &lt;em&gt;new&lt;&#x2F;em&gt; innovations, but instead
provide a lens through which we can look at a general group of challenges and
the tools that help address them.&lt;&#x2F;p&gt;
&lt;p&gt;I think the Rust compiler truly nailed the ergonomics of reporting errors during
compilation. My hope is that someday we&#x27;ll be have a similarly cohesive UX for
runtime errors too.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;ekuber&quot;&gt;ekuber&lt;&#x2F;a&gt; for all the work he&#x27;s done on
compiler diagnostics, and a very entertaining chat during Rustconf about
diagnostics.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Async Builders</title>
            <pubDate>Sat, 21 Sep 2019 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/async-finalizers/</link>
            <guid>https://blog.yoshuawuyts.com/async-finalizers/</guid>
            <description>&lt;p&gt;Last month we introduced &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;surf&#x2F;&quot;&gt;Surf&lt;&#x2F;a&gt;, an async
cross-platform streaming HTTP client for Rust. It was met with a great
reception, and people generally seem to be really enjoying it.&lt;&#x2F;p&gt;
&lt;p&gt;A common piece of feedback we&#x27;ve gotten is how much people enjoy the interface,
in particular how little code it requires to create HTTP requests.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;surf::get(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;https:&#x2F;&#x2F;example.com&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this post we&#x27;ll cover a pattern at the heart of Surf&#x27;s ergonomics
&lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;stjepang&#x2F;&quot;&gt;stjepang&lt;&#x2F;a&gt; came up with: the &quot;async finalizer&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Note: it&#x27;s probably worth setting some expectations at this point. This post is
unfortunately not about async destructors. I&#x27;m sorry if this is disappointing.
Trust me, I want them too.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;refresher-builder-pattern&quot;&gt;Refresher: builder pattern&lt;&#x2F;h2&gt;
&lt;p&gt;In languages such as JavaScript it&#x27;s common to pass options objects to provide
configuration. You define an object, set some parameters, and often pass it as
an optional extra argument to a function.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; default
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;app &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;choo&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; with options
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;opts &lt;&#x2F;span&gt;&lt;span&gt;= { hash: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;app &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;choo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;opts&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However in Rust this doesn&#x27;t quite work the same because of how the type
system&#x27;s rules. Instead there are a few different different ways of defining
configuration, of which one of the most common variants is the builder patter.&lt;&#x2F;p&gt;
&lt;p&gt;Instead of passing options into a constructor, you create a configuration struct
with methods to set options, and one final method that takes the config and
outputs the struct you wanted. An example from std is &lt;code&gt;fs::OpenOptions&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::fs::OpenOptions;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; file = OpenOptions::new()
&lt;&#x2F;span&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;create&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;foo.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In the case of &lt;code&gt;OpenOptions&lt;&#x2F;code&gt; the &lt;code&gt;open&lt;&#x2F;code&gt; method converts the configuration into a
&lt;code&gt;File&lt;&#x2F;code&gt;. The &lt;code&gt;open&lt;&#x2F;code&gt; method is what we refer to as the &quot;finalizer&quot; method.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;note: &lt;code&gt;OpenOptions&lt;&#x2F;code&gt; is a bit special because it can be reused. It&#x27;s exceedingly
common for builders to consume the configuration in their finalizer, as we do in
Surf.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;await-and-the-borrow-checker&quot;&gt;Await and the borrow checker&lt;&#x2F;h2&gt;
&lt;p&gt;In Async Rust the builder pattern that was shown above works perfectly fine. But
because of how &lt;code&gt;await&lt;&#x2F;code&gt; works some interesting options open up. In particular we
can lean on the property of &lt;code&gt;await&lt;&#x2F;code&gt; that the compiler statically ensures the
same future is not awaited twice.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::future;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;async_attributes&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; fut = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    fut.await;
&lt;&#x2F;span&gt;&lt;span&gt;    fut.await; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; this is invalid
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;error[E0382]: use of moved value: `fut`
&lt;&#x2F;span&gt;&lt;span&gt;  --&amp;gt; examples&#x2F;logging.rs:11:9
&lt;&#x2F;span&gt;&lt;span&gt;   |
&lt;&#x2F;span&gt;&lt;span&gt;9  |    let fut = async_std::future::ready(1u8);
&lt;&#x2F;span&gt;&lt;span&gt;   |        --- move occurs because `fut` has type `impl std::future::Future`, which does not implement the `Copy` trait
&lt;&#x2F;span&gt;&lt;span&gt;10 |    fut.await;
&lt;&#x2F;span&gt;&lt;span&gt;   |    --------- value moved here
&lt;&#x2F;span&gt;&lt;span&gt;11 |    fut.await;
&lt;&#x2F;span&gt;&lt;span&gt;   |    ^^^ value used here after move
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;error: aborting due to previous error
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This compiler error occurs because &lt;code&gt;await&lt;&#x2F;code&gt; takes futures by value, not by
reference (&lt;code&gt;self&lt;&#x2F;code&gt; vs &lt;code&gt;&amp;amp;self&lt;&#x2F;code&gt;). Which is exactly the property we want for a
consuming finalizer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;async-finalizers&quot;&gt;Async Finalizers&lt;&#x2F;h2&gt;
&lt;p&gt;In Surf we started off with a &lt;code&gt;send&lt;&#x2F;code&gt; method as the finalizer, but it never felt
quite right. This is because &lt;code&gt;await&lt;&#x2F;code&gt; filled a similar role already, and &lt;code&gt;send&lt;&#x2F;code&gt;
was essentially redundant. Once we realized we were swiftly able to remove it,
and the resulting API felt a lot nicer.&lt;&#x2F;p&gt;
&lt;p&gt;We still have a
few special-purpose finalizers such as
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;surf&#x2F;1.0.2&#x2F;surf&#x2F;struct.Request.html#method.recv_json&quot;&gt;&lt;code&gt;recv_json&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;,
but we only use those to reduce the amount of instances of &lt;code&gt;await&lt;&#x2F;code&gt; for shorter
scripts.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;surf::get(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;https:&#x2F;&#x2F;example.com&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;().await?; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; old
&lt;&#x2F;span&gt;&lt;span&gt;surf::get(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;https:&#x2F;&#x2F;example.com&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; new
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;await&lt;&#x2F;code&gt; is the primary way the &lt;code&gt;Request&lt;&#x2F;code&gt; builder now terminates, and returns a
&lt;code&gt;Result&amp;lt;Response&amp;gt;&lt;&#x2F;code&gt;. Because if you think of it: a request really is a fancy
configuration option that&#x27;s submitted to the server to get what you really want:
a response.&lt;&#x2F;p&gt;
&lt;p&gt;The way we&#x27;ve implemented this is more or less &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustasync&#x2F;surf&#x2F;blob&#x2F;master&#x2F;src&#x2F;request.rs#L563-L586&quot;&gt;like
this&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Future &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Request {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output = Result&amp;lt;Response, Exception&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Construct a future once, and store it internally.
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.fut.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_none&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.fut = Some(Box::pin(async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = Next::new(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.middleware)
&lt;&#x2F;span&gt;&lt;span&gt;                    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.req, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.client)
&lt;&#x2F;span&gt;&lt;span&gt;                    .await?;
&lt;&#x2F;span&gt;&lt;span&gt;                Ok(Response::new(res))
&lt;&#x2F;span&gt;&lt;span&gt;            }));
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Now that we have an inner future, we can forward all poll calls to
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; it until it resolves.
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.fut.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(cx)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This pattern can be implemented in many different ways, but the core of it is to
implement the &lt;code&gt;Future&lt;&#x2F;code&gt; trait on the builder itself.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;addendum-future-ergonomic-improvements&quot;&gt;Addendum: Future ergonomic improvements&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;d7acl0&#x2F;async_finalizers&#x2F;f0ytyyj&quot;&gt;As was pointed out by
nemo157&lt;&#x2F;a&gt;,
it&#x27;s interesting to consider how this would interact with the &lt;code&gt;IntoFuture&lt;&#x2F;code&gt;
trait.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-preview&#x2F;0.3.0-alpha.18&#x2F;futures&#x2F;future&#x2F;struct.IntoFuture.html?search=intofuture&quot;&gt;&lt;code&gt;futures-preview&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
no longer has this trait, but
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures&#x2F;0.1.29&#x2F;futures&#x2F;future&#x2F;trait.IntoFuture.html?search=intofuture&quot;&gt;&lt;code&gt;futures@0.1&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
used to have it. There&#x27;s also a mention of it in last year&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;blob&#x2F;master&#x2F;text&#x2F;2394-async_await.md#the-await-compiler-built-in&quot;&gt;&lt;code&gt;async&#x2F;await&lt;&#x2F;code&gt;
RFC&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The idea is that if we had a trait &lt;code&gt;IntoFuture&lt;&#x2F;code&gt;, and &lt;code&gt;await&lt;&#x2F;code&gt; is the keyword
to call &lt;code&gt;.into_future()&lt;&#x2F;code&gt; and then poll the future to completion. This would
allow us to get rid of boxing the future, and then driving it to completion
ourselves, which would be more performant and easier to implement.&lt;&#x2F;p&gt;
&lt;p&gt;All together the usage would remain exactly the same, but the definition could
be simplified:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Trait definition.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mod &lt;&#x2F;span&gt;&lt;span&gt;std {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mod &lt;&#x2F;span&gt;&lt;span&gt;future {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;IntoFuture {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Future: Future&amp;lt;Output = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into_future&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Future;
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Example usage in surf.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; We could construct a manual future here instead of `BoxFuture`, but for the
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; purposes of the demo we won&amp;#39;t.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;std::future::IntoFuture &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Request {
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Output = Result&amp;lt;Response, Exception&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Future = Pin&amp;lt;Box&amp;lt;dyn Future&amp;lt;Output = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; + Send&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;into_future&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Future {
&lt;&#x2F;span&gt;&lt;span&gt;         Box::pin(async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = Next::new(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.middleware)
&lt;&#x2F;span&gt;&lt;span&gt;                 .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.req, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.client)
&lt;&#x2F;span&gt;&lt;span&gt;                 .await?;
&lt;&#x2F;span&gt;&lt;span&gt;             Ok(Response::new(res))
&lt;&#x2F;span&gt;&lt;span&gt;         })
&lt;&#x2F;span&gt;&lt;span&gt;     }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Even though we&#x27;ve cheated a little with the lifetimes of &lt;code&gt;Pin&amp;lt;Box&amp;gt;&lt;&#x2F;code&gt;, it
definitely feels like it removes some of the rough edges around async
finalizers. I haven&#x27;t seen &lt;code&gt;IntoFuture&lt;&#x2F;code&gt; being mentioned anywhere in the
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;62149&quot;&gt;async&#x2F;await stabilization
report&lt;&#x2F;a&gt;, which leads me to
believe that the omission from the async&#x2F;await MVP stabilization is mostly
because it simply hasn&#x27;t been deemed a priority.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;extra-guarding-against-manual-re-polling&quot;&gt;Extra: guarding against manual re-polling&lt;&#x2F;h2&gt;
&lt;p&gt;The only caveat in the (simplified) example above is that it doesn&#x27;t provide a
nice error message if manually polled repeated multiple times. In the actual
implementation the inner values are &lt;code&gt;Option&lt;&#x2F;code&gt;s that we &lt;code&gt;take&lt;&#x2F;code&gt;, which means the
builder would panic if polled after completion. But we can do better.&lt;&#x2F;p&gt;
&lt;p&gt;By having &lt;code&gt;debug_assert&lt;&#x2F;code&gt; and keeping an inner flag we can provide a slightly
nicer error message for this case. This would look something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Context&amp;lt;&amp;#39;_&amp;gt;) -&amp;gt; Poll&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Output&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;  debug_assert!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.is_resolved == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Cannot poll future after being resolved&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Construct the future here
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = future::ready!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.fut.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_mut&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;poll&lt;&#x2F;span&gt;&lt;span&gt;(cx));
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.is_resolved = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  Poll::Ready(res)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;extra-javascript-promises&quot;&gt;Extra: JavaScript Promises&lt;&#x2F;h2&gt;
&lt;p&gt;This pattern is so nice, you might wonder why other languages don&#x27;t have this.
In particular &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;WindowOrWorkerGlobalScope&#x2F;fetch&quot;&gt;JavaScript&#x27;s &lt;code&gt;Fetch&lt;&#x2F;code&gt;
API&lt;&#x2F;a&gt;
uses async&#x2F;await, and yet doesn&#x27;t have this pattern.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;myRequest &lt;&#x2F;span&gt;&lt;span&gt;= new Request(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;flowers.jpg&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;, {
&lt;&#x2F;span&gt;&lt;span&gt;  method: &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;GET&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;,
&lt;&#x2F;span&gt;&lt;span&gt;  cache: &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;default&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;res &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;await &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;fetch&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;myRequest&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is because Rust&#x27;s futures are &lt;em&gt;lazy&lt;&#x2F;em&gt;; they don&#x27;t do anything until &lt;code&gt;poll&lt;&#x2F;code&gt;
or &lt;code&gt;.await&lt;&#x2F;code&gt; is called on them. JavaScript&#x27;s promises are &lt;em&gt;eager&lt;&#x2F;em&gt;; they start
running the moment they&#x27;re constructed. This means that construction of the
promise needs to be separated from construction of the options.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;addendum:&lt;&#x2F;strong&gt; as was &lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;d7acl0&#x2F;async_finalizers&#x2F;f0yspq9&#x2F;&quot;&gt;pointed
out by tehdog&lt;&#x2F;a&gt;
it&#x27;s actually possible to achieve do this in JavaScript using &quot;thenables&quot;. That
is: any object that has a &lt;code&gt;then&lt;&#x2F;code&gt; method on its prototype can be awaited as if it
were a Promise, but unlike Promises isn&#x27;t run until awaited. This enables lazy
evaluation in JavaScript, much like in Rust.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;Request &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eff1f5;&quot;&gt;{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eff1f5;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;constructor&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;url&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eff1f5;&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eff1f5;&quot;&gt;{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eff1f5;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;this&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eff1f5;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;url &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;url
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eff1f5;&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eff1f5;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;then&lt;&#x2F;span&gt;&lt;span&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eff1f5;&quot;&gt;{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eff1f5;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;fetch&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eff1f5;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;this&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eff1f5;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;url&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eff1f5;&quot;&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eff1f5;&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eff1f5;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x &lt;&#x2F;span&gt;&lt;span&gt;= new Request(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Request is constructed, no I&#x2F;O happens.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;res &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;await &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Request is sent, I&#x2F;O happens here.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve more closely examined the &quot;async finalizer&quot; pattern which
underpins some of Surf&#x27;s biggest ergonomic conveniences. We&#x27;ve explained what
builders are, how they work, and how we can achieve the same results in async
code using the &lt;code&gt;Future&lt;&#x2F;code&gt; trait.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m really happy we figured this out, and since we&#x27;ve released Surf we&#x27;ve seen
this same pattern being used in some other places too. We&#x27;re probably not the
first people to think of this pattern, but I&#x27;m pretty sure neither Stjepan nor I
had seen this before when Stjepan proposed we use it. And I figured it&#x27;d be
worth writing about so more people can find out about this!&lt;&#x2F;p&gt;
&lt;p&gt;In general I feel this it&#x27;s still early days in the design space around
async&#x2F;await. As time goes on it seems likely we&#x27;ll discover more patterns like
these, and eventually induct them into a well-known set of &quot;best practices&quot;.
This is my attempt at sharing a neat little pattern we found, in the hope that
more people will discover it and be able to pick it up.&lt;&#x2F;p&gt;
&lt;p&gt;As always, thanks for reading! I hope this was helpful!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Futures Concurrency I: Introduction</title>
            <pubDate>Mon, 02 Sep 2019 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/futures-concurrency/</link>
            <guid>https://blog.yoshuawuyts.com/futures-concurrency/</guid>
            <description>&lt;p&gt;In a previous post we&#x27;ve looked at &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;rust-streams&#x2F;&quot;&gt;Rust
streams&lt;&#x2F;a&gt;. In this post we&#x27;re going
to discuss another problem in the async space: futures concurrency combinators.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;re going to cover the different forms of concurrency that can be expressed
with Futures, and cover both &lt;a href=&quot;&#x2F;contexts&#x2F;&quot;&gt;fallible and infallible variants&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;For the sake of this article I&#x27;m going to assume you&#x27;re already familiar with
Futures as a mechanism for scheduling async work. If you&#x27;re not, I recommend
starting with the &lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;async-book&#x2F;index.html&quot;&gt;Rust async
book&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;futures-concurrency&quot;&gt;Futures Concurrency&lt;&#x2F;h2&gt;
&lt;p&gt;In general when you&#x27;re running Futures you can schedule them in one of 3 ways:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Run a future, and wait for it to complete.&lt;&#x2F;li&gt;
&lt;li&gt;Run multiple futures, and wait for all of them to complete.&lt;&#x2F;li&gt;
&lt;li&gt;Run multiple futures, and wait for the first one to complete.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The first way of scheduling futures is &quot;sequential&quot;, and the default if we
&lt;code&gt;await&lt;&#x2F;code&gt; multiple futures in a row. The other two scheduling approaches are
&quot;concurrent&quot;, and have some nuances and variations to them. We also distinguish
between &quot;fallible&quot; and &quot;infallible&quot;, where we&#x27;ll start with the infallible
versions first.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;infallible-join&quot;&gt;Infallible: Join&lt;&#x2F;h2&gt;
&lt;p&gt;The first concurrent approach is &quot;parallel&quot;. In this mode we have a multiple
futures that we &lt;em&gt;all&lt;&#x2F;em&gt; want to complete. We await them all together, and write
the result of each future to a tuple. An example of this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::future;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::join(a, b);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(c.await, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Where the function signature would be:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt; async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;L, R, T1, T2&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;left&lt;&#x2F;span&gt;&lt;span&gt;: L, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;right&lt;&#x2F;span&gt;&lt;span&gt;: R) -&amp;gt; (T1, T2)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where&lt;&#x2F;span&gt;&lt;span&gt; L: Future&amp;lt;Output = T1&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;          R: Future&amp;lt;Output = T2&amp;gt;;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we want to join more than two futures we can nest calls to &lt;code&gt;join&lt;&#x2F;code&gt;, and
later in this post we&#x27;ll look at possible ways to make this an even better
experience.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;infallible-select&quot;&gt;Infallible: Select&lt;&#x2F;h2&gt;
&lt;p&gt;The other form of concurrency is having multiple futures, and wanting &lt;em&gt;one&lt;&#x2F;em&gt; to
resolve. This is generally less common than waiting for &lt;em&gt;all&lt;&#x2F;em&gt; futures to
resolve, but still useful when for example wanting to set a time limit on a
future.&lt;&#x2F;p&gt;
&lt;p&gt;There are many concurrency scenarios imaginable, but in general this means
waiting for the &lt;em&gt;first&lt;&#x2F;em&gt; future to resolve. This is generally done through the
&lt;code&gt;select&lt;&#x2F;code&gt; function. An example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::future;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::pending();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::select(a, b);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(c.await, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Where the function signature would be:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt; async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;select&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;F, T&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;left&lt;&#x2F;span&gt;&lt;span&gt;: F, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;right&lt;&#x2F;span&gt;&lt;span&gt;: F) -&amp;gt; T
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where&lt;&#x2F;span&gt;&lt;span&gt; F: Future&amp;lt;Output = T&amp;gt;;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;summary-infallible-functions&quot;&gt;Summary: Infallible functions&lt;&#x2F;h2&gt;
&lt;p&gt;For operating on infallible futures (e.g. futures that don&#x27;t return &lt;code&gt;Result&lt;&#x2F;code&gt;),
we&#x27;ve defined the following methods:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Name&lt;&#x2F;th&gt;&lt;th&gt;Return signature&lt;&#x2F;th&gt;&lt;th&gt;When does it return?&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;future::join&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;(T1, T2)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Wait for all to complete&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;future::select&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;T&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Return on first value&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Let&#x27;s move onto fallible futures next!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fallible-join&quot;&gt;Fallible: Join&lt;&#x2F;h2&gt;
&lt;p&gt;When calling &lt;code&gt;join&lt;&#x2F;code&gt; on two futures that return &lt;code&gt;Result&lt;&#x2F;code&gt;, being handed back a
&lt;code&gt;(Result&amp;lt;T, E&amp;gt;, Result&amp;lt;T, E&amp;gt;)&lt;&#x2F;code&gt; makes error handling rather awkward:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::future;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(Ok(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(Ok(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::join(a, b).await;
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!((c.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;?, c.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;?), (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; this is not great
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Instead it&#x27;d be much nicer if we were handed back a &lt;code&gt;Result&amp;lt;(T1, T2), E&amp;gt;&lt;&#x2F;code&gt;, so we
could handle errors more or less like we&#x27;d expect to:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::future;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(Ok(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(Ok(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::try_join(a, b);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(c.await?, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; much better
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This introduces a new function &lt;code&gt;try_join&lt;&#x2F;code&gt; with a signature of:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt; async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;try_join&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;L, R, T1, T2, E&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;left&lt;&#x2F;span&gt;&lt;span&gt;: L, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;right&lt;&#x2F;span&gt;&lt;span&gt;: R) -&amp;gt; Result&amp;lt;(T1, T2), E&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where&lt;&#x2F;span&gt;&lt;span&gt; L: Future&amp;lt;Output = Result&amp;lt;T1, E&amp;gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;          R: Future&amp;lt;Output = Result&amp;lt;T2, E&amp;gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;An implication of the API returning &lt;code&gt;Result&amp;lt;(T1, T2), E&amp;gt;&lt;&#x2F;code&gt; is that if either of the
futures returns &lt;code&gt;Err&lt;&#x2F;code&gt;, we should drop the other future because it will never
yield its result. This is commonly referred to as &lt;em&gt;early rejection&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If it&#x27;s undesirable to reject early, using &lt;code&gt;join&lt;&#x2F;code&gt; instead of &lt;code&gt;try_join&lt;&#x2F;code&gt; allows
&lt;em&gt;all&lt;&#x2F;em&gt; futures to complete before returning.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fallible-select&quot;&gt;Fallible: Select&lt;&#x2F;h2&gt;
&lt;p&gt;Like we said earlier, the purpose of &lt;code&gt;select&lt;&#x2F;code&gt; is to get back the first result
from multiple futures. However, say we want to check both our local cache and a
remote cache if something is stored there, we don&#x27;t necessarily care if either
of them fails, as long as one of them has the result we want. We cannot express
this using the regular &lt;code&gt;select&lt;&#x2F;code&gt; function:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::future;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(err!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;oh no!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; some error
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(Ok(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::select(a, b);
&lt;&#x2F;span&gt;&lt;span&gt;assert!(c.await.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_err&lt;&#x2F;span&gt;&lt;span&gt;()); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; if `a` is an error, we cannot proceed to `b`
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The semantics we want are: &quot;give back the first response that succeeds, or
if none of them succeed return the last error.&quot;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::future;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(err!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;oh no!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; some error
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(Ok(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::try_select(a, b);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(c.await?, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; `a` failed, `b` succeeded -- so we get `b`
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Where the function signature would be:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span&gt; async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;try_select&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;F, T, E&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;left&lt;&#x2F;span&gt;&lt;span&gt;: F, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;right&lt;&#x2F;span&gt;&lt;span&gt;: F) -&amp;gt; Result&amp;lt;T, E&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where&lt;&#x2F;span&gt;&lt;span&gt; F: Future&amp;lt;Output = Result&amp;lt;T, E&amp;gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If it&#x27;s undesirable to get keep trying until all options have been exhausted,
then it&#x27;s acceptable to use &lt;code&gt;select&lt;&#x2F;code&gt; for fallible futures too, to get the
&lt;em&gt;first&lt;&#x2F;em&gt; future regardless of whether it succeeded, and reject early if it failed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary-fallible-functions&quot;&gt;Summary: Fallible functions&lt;&#x2F;h2&gt;
&lt;p&gt;When talking about fallible futures, we have access to a total of 4 functions:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Name&lt;&#x2F;th&gt;&lt;th&gt;Return signature&lt;&#x2F;th&gt;&lt;th&gt;When does it return?&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;future::join&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;(Result&amp;lt;T, E&amp;gt;, Result&amp;lt;T, E&amp;gt;)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Wait for all to complete&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;future::try_join&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Result&amp;lt;(T1, T2), E&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Return on first &lt;code&gt;Err&lt;&#x2F;code&gt;, wait for all to complete&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;future::select&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Result&amp;lt;T, E&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Return on first value&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;future::try_select&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Result&amp;lt;T, E&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Return on first &lt;code&gt;Ok&lt;&#x2F;code&gt;, reject on last Err&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;In most cases the &lt;code&gt;try_&lt;&#x2F;code&gt; functions will be the right choice for fallible
futures, but in the off chance it&#x27;s not, the regular variants allow bypassing
the semantics to do more custom things. And even better: by mixing both kinds
of functions, more complicated flows can be created.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;variadics&quot;&gt;Variadics&lt;&#x2F;h2&gt;
&lt;p&gt;The functions we&#x27;ve talked about so far are quite nice, but it&#x27;s not rare to
want &lt;code&gt;join&lt;&#x2F;code&gt; or &lt;code&gt;select&lt;&#x2F;code&gt; more than two futures. A way to do this is to apply
combinators multiple times:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::future;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; j = future::join(a, b);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; k = future::join(j, c);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(k.await, ((&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;)); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; this is probably not great to work with though
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Instead it&#x27;d be much nicer if we could provide an &lt;code&gt;n&lt;&#x2F;code&gt; length input, and get back
an &lt;code&gt;n&lt;&#x2F;code&gt; length tuple. The way to do this is through &lt;em&gt;variadics&lt;&#x2F;em&gt;; functions with
varying input. The way we can write &lt;em&gt;variadics&lt;&#x2F;em&gt; in Rust today is by using
macros:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_std::future;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; j = future::join!(a, b, c);
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(j.await, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;)); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; much better
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Being able to accept multiple arguments is useful for all methods we&#x27;ve
described so far. Additionally all of them could, and probably should, be
written as variadics rather than regular functions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;methods&quot;&gt;Methods&lt;&#x2F;h2&gt;
&lt;p&gt;So far we&#x27;ve only talked about &quot;free functions&quot; (standalone functions), and not
&quot;methods&quot; (functions that are part of a &lt;code&gt;struct&lt;&#x2F;code&gt;). In Rust, structs can&#x27;t have
associated macros, which means that variadics wouldn&#x27;t be possible there, which
in turn means we&#x27;d lose out on ergonomics.&lt;&#x2F;p&gt;
&lt;p&gt;But there&#x27;s another reason: to our knowledge it&#x27;s currently impossible to define
the &lt;code&gt;try_&lt;&#x2F;code&gt; variants directly on &lt;code&gt;Future&lt;&#x2F;code&gt; without introducing an intermediate
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-preview&#x2F;0.3.0-alpha.17&#x2F;futures&#x2F;future&#x2F;trait.TryFuture.html&quot;&gt;&lt;code&gt;TryFuture&lt;&#x2F;code&gt; type&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In the future specialization might make it possible to implement the &lt;code&gt;try_&lt;&#x2F;code&gt;
methods for futures with the right signature. But in the mean time if we&#x27;re
thinking of the core concurrency mechanisms and how they may some day live in
std, having them be variadic free functions seems like the better choice all
around.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;async-concurrency-javascript&quot;&gt;Async Concurrency: JavaScript&lt;&#x2F;h2&gt;
&lt;p&gt;JavaScript is an asynchronous-first language that in recent years has chosen
&lt;code&gt;Promise&lt;&#x2F;code&gt; + &lt;code&gt;async&#x2F;await&lt;&#x2F;code&gt; as its core concurrency mechanism. There are two core
differences between JavaScript Promises and Rust&#x27;s Futures:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;When a &lt;code&gt;Promise&lt;&#x2F;code&gt; is created it is immediately scheduled on the microtask
queue (executor), while in Rust a &lt;code&gt;Futures&lt;&#x2F;code&gt; is only scheduled when
&lt;code&gt;.await&lt;&#x2F;code&gt;ed.&lt;&#x2F;li&gt;
&lt;li&gt;Every &lt;code&gt;Promise&lt;&#x2F;code&gt; in JavaScript is fallible (&lt;code&gt;reject&#x2F;resolve&lt;&#x2F;code&gt;), while a Rust
&lt;code&gt;Future&lt;&#x2F;code&gt; can be either fallible or infallible, depending on whether it
returns a &lt;code&gt;Result&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Since &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tc39&#x2F;proposal-promise-allSettled&quot;&gt;the last TC39
meeting&lt;&#x2F;a&gt;, JavaScript has
the following 4 methods for concurrency in Promises:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;name&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;signature&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;description&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;stage&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Promise.allSettled&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;(iterable)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;does not short-circuit&lt;&#x2F;td&gt;&lt;td&gt;4 (stable)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Promise.all&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;(iterable)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;short-circuits when an input value is rejected&lt;&#x2F;td&gt;&lt;td&gt;4 (stable)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Promise.race&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;(iterable)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;short-circuits when an input value is settled&lt;&#x2F;td&gt;&lt;td&gt;4 (stable)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Promise.any&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;(iterable)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;short-circuits when an input value is fulfilled&lt;&#x2F;td&gt;&lt;td&gt;2 (experimental)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;What we&#x27;re proposing in this post is fairly similar, but unlike JavaScript we&#x27;re
able to discern between fallible &#x2F; infallible Futures which makes allows us to
make use of that in the design. In fact, for fallible Futures they compare
really well:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;JavaScript&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Rust&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;description&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Promise.allSettled&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;future::join&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;does not short-circuit&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Promise.all&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;future::try_join&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;short-circuits when an input value is rejected&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Promise.race&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;future::select&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;short-circuits when an input value is settled&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Promise.any&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;future::try_select&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;short-circuits when an input value is fulfilled&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;async-concurrency-golang&quot;&gt;Async Concurrency: Golang&lt;&#x2F;h2&gt;
&lt;p&gt;So I&#x27;m by no means a Golang expert, but I know we&#x27;ve been looking at it quite a
bit when trying to figure out futures concurrency. In particular the Golang
&lt;a href=&quot;https:&#x2F;&#x2F;golangbot.com&#x2F;select&#x2F;&quot;&gt;&lt;code&gt;select&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; blocks have an equivalent in the
existing
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-preview&#x2F;0.3.0-alpha.18&#x2F;futures&#x2F;macro.select.html&quot;&gt;&lt;code&gt;futures::select&lt;&#x2F;code&gt; macro&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures::select;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; a = future::ready(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; b = future::pending::&amp;lt;()&amp;gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = select! {
&lt;&#x2F;span&gt;&lt;span&gt;    a_res = a =&amp;gt; a_res + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    _ = b =&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;assert_eq!(res, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It seems well-understood that the macro in its current form wouldn&#x27;t make it
into the standard library. Which would mean that this form of &lt;code&gt;select&lt;&#x2F;code&gt; would
probably need to be elevated to the language level, which would require a fair
amount of design work, and at waiting until at least a new edition.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Side note: this is not to say that I&#x27;m proposing the addition of any API to
stdlib quite yet. But I like to consider the possibility that at some point in
the future we may want to. So in order to have a fruitful conversation about
whether we should, I want to make sure we don&#x27;t have to question whether we
could.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;While &lt;code&gt;select&lt;&#x2F;code&gt; blocks seem cool, I think it&#x27;d be preferable if we could solve
the same problems without needing changes to the language. And I think with the
&lt;code&gt;select&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;try_select&lt;&#x2F;code&gt; functions we&#x27;re proposing we do!&lt;&#x2F;p&gt;
&lt;p&gt;The biggest difference with Go&#x27;s &lt;code&gt;select&lt;&#x2F;code&gt; blocks is that all &quot;branches&quot; in our
&lt;code&gt;select&lt;&#x2F;code&gt; functions resolve to the same type, while in at least the Rust&#x2F;Go
version it seems like it&#x27;s possible to return multiple return types &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-preview&#x2F;0.3.0-alpha.18&#x2F;futures&#x2F;future&#x2F;fn.select.html&quot;&gt;trough an
&lt;code&gt;Either&lt;&#x2F;code&gt; type&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pattern-log-all-errors-in-try-select&quot;&gt;Pattern: log all errors in &lt;code&gt;try_select&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;One question that comes up frequently is: &quot;how do I log &lt;em&gt;all&lt;&#x2F;em&gt; errors inside a
&lt;code&gt;select&lt;&#x2F;code&gt; call?&quot; The way to do that is to &lt;code&gt;map_err&lt;&#x2F;code&gt; (or equivalent) the future
before passing it to &lt;code&gt;select&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;e&lt;&#x2F;span&gt;&lt;span&gt;| dbg!(e));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = b.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;e&lt;&#x2F;span&gt;&lt;span&gt;| dbg!(e));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::try_select(a, b).await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If &lt;code&gt;map_err&lt;&#x2F;code&gt; is not available (as is the case with &lt;code&gt;async_std&lt;&#x2F;code&gt;), it&#x27;s possible
to achieve the same behavior by defining a new async block:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; a = async { Ok(a.await.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(dbg!(e))?) }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; b = async { Ok(b.await.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(dbg!(e))?) }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; c = future::try_select(a, b).await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve covered the challenges of both fallible and infallible async
concurrency in Rust, compared it to approaches from two different languages, and
formulated a coherent model that covers all cases.&lt;&#x2F;p&gt;
&lt;p&gt;The next step for this proposal is to write experimental implementations for
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-std&#x2F;0.99.4&#x2F;async_std&#x2F;&quot;&gt;&lt;code&gt;async-std&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to see how well it
works in practice.&lt;&#x2F;p&gt;
&lt;p&gt;In the future we may also want to cover streams concurrency. In particular ways
we could improve upon &lt;code&gt;Stream::for_each_concurrent&lt;&#x2F;code&gt; &#x2F;
&lt;code&gt;Stream::try_for_each_concurrent&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;Stream::FuturesUnordered&lt;&#x2F;code&gt; seem like an
interesting topic. But that&#x27;s not in scope for today.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks all for reading, and have a good week!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Special thanks to Tirr-c and David Barsky for proof reading!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>surf</title>
            <pubDate>Wed, 14 Aug 2019 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/surf/</link>
            <guid>https://blog.yoshuawuyts.com/surf/</guid>
            <description>&lt;p&gt;Today we&#x27;re happy to announce &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustasync&#x2F;surf&quot;&gt;&lt;code&gt;Surf&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, an asynchronous cross-platform streaming
HTTP client for Rust. This project was a collaboration between &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;zkat&#x2F;&quot;&gt;Kat
Marchán&lt;&#x2F;a&gt; (Entropic &#x2F; Microsoft), &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;stjepang&#x2F;&quot;&gt;Stjepan
Glavina&lt;&#x2F;a&gt; (Ferrous Systems), and myself (Yoshua
Wuyts).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ergonomics&quot;&gt;Ergonomics&lt;&#x2F;h2&gt;
&lt;p&gt;Surf is a friendly HTTP client built for casual Rustaceans and veterans alike.
It&#x27;s completely modular, works directly with &lt;code&gt;async&#x2F;await&lt;&#x2F;code&gt;, and is easy to use.
Whether it&#x27;s a quick script, or a full SDK, Surf will make it work.&lt;&#x2F;p&gt;
&lt;p&gt;Take for example the classic GET request. With Surf it&#x27;s one line to make a
request and print the response.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;dbg!(surf::get(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;https:&#x2F;&#x2F;example.com&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Similarly sending and receiving JSON is real easy too thanks to integration with
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;serde&#x2F;1.0.98&#x2F;serde&#x2F;&quot;&gt;&lt;code&gt;serde&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = surf::post(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;https:&#x2F;&#x2F;httpbin.org&#x2F;post&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;body_json&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;json!({ &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;: &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;rey&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; }))?
&lt;&#x2F;span&gt;&lt;span&gt;    .await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Deserialize)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Ip { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ip&lt;&#x2F;span&gt;&lt;span&gt;: String }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; Ip { ip } = surf::get(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;https:&#x2F;&#x2F;api.ipify.org?format=json&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;recv_json&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And even better: we fully support streaming inbound and outbound request bodies.
Not only can we upload files directly and while figuring out the Media Types
(MIME) for you. You can also pass requests as the bodies to other requests,
making it really convenient to proxy requests.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = surf::post(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;https:&#x2F;&#x2F;httpbin.org&#x2F;post&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;body&lt;&#x2F;span&gt;&lt;span&gt;(surf::get(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;https:&#x2F;&#x2F;httpbin.org&#x2F;get&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?)
&lt;&#x2F;span&gt;&lt;span&gt;    .await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;write-once-run-everywhere&quot;&gt;Write once, run everywhere&lt;&#x2F;h2&gt;
&lt;p&gt;One our main inspirations for &lt;code&gt;Surf&lt;&#x2F;code&gt; has been
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;zkat&#x2F;make-fetch-happen&quot;&gt;&lt;code&gt;make-fetch-happen&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which is a
JavaScript client that provides a convenient user interface for Node.js, built
on top of the cross-platform
&lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;WindowOrWorkerGlobalScope&#x2F;fetch&quot;&gt;&lt;code&gt;fetch&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
API.&lt;&#x2F;p&gt;
&lt;p&gt;Similarly we wanted to make sure &lt;code&gt;Surf&lt;&#x2F;code&gt; works in lots of environments, and
thanks to the help of the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustwasm&#x2F;&quot;&gt;Rust WASM WG&lt;&#x2F;a&gt; we were
able to get really far on this! Out of the box &lt;code&gt;Surf&lt;&#x2F;code&gt; will work on Linux, MacOS,
Windows and in browsers. Setting it up in the browser is a matter of using
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;wasm-bindgen-futures&#x2F;&quot;&gt;&lt;code&gt;wasm-bindgen-futures&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, and you should
be good to go:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;wasm_bindgen&lt;&#x2F;span&gt;&lt;span&gt;(start)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Result&amp;lt;(), surf::Exception&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        femme::start(log::LevelFilter::Trace)?;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; body = surf::get(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;https:&#x2F;&#x2F;httpbin.org&#x2F;get&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;recv_string&lt;&#x2F;span&gt;&lt;span&gt;().await?;
&lt;&#x2F;span&gt;&lt;span&gt;        log::info!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, body);
&lt;&#x2F;span&gt;&lt;span&gt;        Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn_local&lt;&#x2F;span&gt;&lt;span&gt;(async {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;().await;
&lt;&#x2F;span&gt;&lt;span&gt;        res.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap_or&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;e&lt;&#x2F;span&gt;&lt;span&gt;| panic!(format!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, e)))
&lt;&#x2F;span&gt;&lt;span&gt;    });
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;This example uses &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;log&quot;&gt;&lt;code&gt;log&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;femme&quot;&gt;&lt;code&gt;femme&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; for logging, and must be built with
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;wasm-pack&quot;&gt;&lt;code&gt;wasm-pack&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Also WASM doesn&#x27;t support returning
&lt;code&gt;Result&lt;&#x2F;code&gt; from &lt;code&gt;start&lt;&#x2F;code&gt; yet, so that&#x27;s why we handle the error manually.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Out of the box &lt;code&gt;Surf&lt;&#x2F;code&gt; uses &lt;code&gt;curl&lt;&#x2F;code&gt; on servers (through
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sagebind&#x2F;isahc&quot;&gt;&lt;code&gt;isahc&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; ✨🐶), and
&lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;WindowOrWorkerGlobalScope&#x2F;fetch&quot;&gt;&lt;code&gt;window.fetch&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
in browsers. Additionally we also ship a
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;runtime&#x2F;0.3.0-alpha.6&#x2F;runtime&#x2F;&quot;&gt;&lt;code&gt;runtime&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;-enabled
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;hyper&#x2F;0.12.33&#x2F;hyper&#x2F;&quot;&gt;&lt;code&gt;hyper&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; backend, which can be used by
enabling the &lt;code&gt;hyper-client&lt;&#x2F;code&gt; feature in &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-toml &quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span&gt;[dependencies.surf]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;version &lt;&#x2F;span&gt;&lt;span&gt;= &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;1.0.0&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;default-features &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;features &lt;&#x2F;span&gt;&lt;span&gt;= [&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hyper-client&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;middleware-logger&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;middleware&quot;&gt;Middleware&lt;&#x2F;h2&gt;
&lt;p&gt;One of the core insights we had early on in development is that whatever needs
we anticipate people might have, it&#x27;s impossible to hit the mark for everyone
out of the box. That&#x27;s why &lt;code&gt;Surf&lt;&#x2F;code&gt; can be extended with &lt;code&gt;middleware&lt;&#x2F;code&gt; to run both
after a request is sent, and after a response is received.&lt;&#x2F;p&gt;
&lt;p&gt;This allows a lot of important functionality to be built as middleware. Examples
include caching, retries, logging, header injection, and more. A basic logger
can be written in a few lines:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;surf::middleware::{Middleware, Request, Response, Next, HttpClient};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures::future::BoxFuture;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Printer;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;C: HttpClient&amp;gt; Middleware&amp;lt;C&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Printer {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;handle&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;req&lt;&#x2F;span&gt;&lt;span&gt;: Request, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;client&lt;&#x2F;span&gt;&lt;span&gt;: C, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;: Next&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;, C&amp;gt;)
&lt;&#x2F;span&gt;&lt;span&gt;      -&amp;gt; BoxFuture&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;, Result&amp;lt;Response, surf::Exception&amp;gt;&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        Box::pin(async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;sending a request!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = next.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(req, client).await?;
&lt;&#x2F;span&gt;&lt;span&gt;            println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;request completed!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;            Ok(res)
&lt;&#x2F;span&gt;&lt;span&gt;        })
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Almost all of this is boilerplate that can be copied between projects, and only
exists because &lt;code&gt;async&lt;&#x2F;code&gt; in traits doesn&#x27;t work quite yet.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-trait&#x2F;0.1.7&#x2F;async_trait&#x2F;&quot;&gt;&lt;code&gt;async-trait&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; exists, but we
couldn&#x27;t get it to work quite yet. We should follow up on this though!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;client-reuse&quot;&gt;Client reuse&lt;&#x2F;h2&gt;
&lt;p&gt;An important part of building &quot;serious&quot; HTTP clients is building out
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Software_development_kit&quot;&gt;SDKs&lt;&#x2F;a&gt; that act as a
dedicated client for a particular endpoint. This is especially convenient
because it means that instead of needing to remember urls and methods, we can
simply &lt;code&gt;cargo add&lt;&#x2F;code&gt; a client and we&#x27;re good to go.&lt;&#x2F;p&gt;
&lt;p&gt;To this purpose &lt;code&gt;Surf&lt;&#x2F;code&gt; supports persistent clients using the &lt;code&gt;Client&lt;&#x2F;code&gt; interface.
Instead of performing one-off requests, these are intended to stick around and
handle &lt;em&gt;many&lt;&#x2F;em&gt; requests.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; client = surf::Client::new();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; req1 = client.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;https:&#x2F;&#x2F;httpbin.org&#x2F;get&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;recv_string&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; req2 = client.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;https:&#x2F;&#x2F;httpbin.org&#x2F;get&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;recv_string&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(str1, str2) = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_join&lt;&#x2F;span&gt;&lt;span&gt;(req1, req2).await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A fun implication of Surf&#x27;s portability means that it&#x27;ll become possible to
write SDKs that will work in &lt;em&gt;any&lt;&#x2F;em&gt; platform. Even better: with &lt;code&gt;Surf&lt;&#x2F;code&gt; it becomes
possible to use the same &lt;code&gt;serde&lt;&#x2F;code&gt; payload definitions on both sides of the wire,
making it possible to add a &lt;em&gt;lot&lt;&#x2F;em&gt; of robustness to (JSON) APIs. We&#x27;re very
excited for the interactions that this will enable.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;It&#x27;s been a fun few weeks since &lt;a href=&quot;https:&#x2F;&#x2F;discourse.entropic.dev&#x2F;t&#x2F;writing-an-http-client-for-dstopic&#x2F;204&quot;&gt;Kat first
raised&lt;&#x2F;a&gt;
that Entropic was looking for a new HTTP client. This is just the start for
&lt;code&gt;Surf&lt;&#x2F;code&gt;. We&#x27;re incredibly happy the direction, and excited to be opening
it up to the rest of the Rust community! You can check out the project on
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustasync&#x2F;surf&quot;&gt;github&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;surf&quot;&gt;crates.io&lt;&#x2F;a&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;surf&quot;&gt;docs.rs&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks for reading, and have a great Thursday!&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;Special thanks to: Kat Marchán, Stjepan Glavina, Prasanna Loganathar, Stephen
Coakley, edef, Wonwoo Choi, Michael Gattozzi, Pauan, Florian Gilcher, Nick
Fitzgerald, Lucio Franco, Alex Crichton, Tyler Neely, the Rust Async Ecosystem
WG, and everyone else who has helped make Surf possible!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>async log</title>
            <pubDate>Sat, 29 Jun 2019 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/async-log/</link>
            <guid>https://blog.yoshuawuyts.com/async-log/</guid>
            <description>&lt;p&gt;Today we&#x27;d like to introduce &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-log&quot;&gt;&lt;code&gt;async-log&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, a general-purpose crate that extends
the standard &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;log&quot;&gt;&lt;code&gt;log&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate with asynchronous metadata. This is a first step in
introducing full-fledged asynchronous tracing capabilities to Rust.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-asynchronous-logging&quot;&gt;What is asynchronous logging?&lt;&#x2F;h2&gt;
&lt;p&gt;When building a &lt;em&gt;synchronous&lt;&#x2F;em&gt; application, log messages can be relied on to
always happen in sequence. But unfortunately synchronous applications are rarely
capable of utilizing system resources to their full potential.&lt;&#x2F;p&gt;
&lt;p&gt;In contrast, concurrent applications make a lot better use of system resources.
But it also means we can no longer rely on log messages to strictly happen in
sequence. In order to make sense of logs in asynchronous applications, we need
to be able to correlate sequences of events with each other:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;a1 -&amp;gt; b1 -&amp;gt; b2 -&amp;gt; a2 -&amp;gt; b3     # raw log stream
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;a1 -------------&amp;gt; a2           # parsed log stream a
&lt;&#x2F;span&gt;&lt;span&gt;      b1 -&amp;gt; b2 -------&amp;gt; b3     # parsed log stream b
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;The raw log stream contains items for both &quot;a&quot; and &quot;b&quot;. With async logging you
want to be able to distinguish between the items for &quot;a&quot;, and the items from
&quot;b&quot;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-does-this-work&quot;&gt;How does this work?&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;async-log&lt;&#x2F;code&gt; provides two extensions to the standard &lt;code&gt;log&lt;&#x2F;code&gt; crate: a &lt;code&gt;span!&lt;&#x2F;code&gt;
macro, and a &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;log&#x2F;0.4.6&#x2F;log&#x2F;trait.Log.html&quot;&gt;&lt;code&gt;log::Log&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; wrapper.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;span!&lt;&#x2F;code&gt; macro creates a pair of log points. One at the start of the scope,
and one at the end of the scope. The macro works with sync and async alike:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;runtime::time::Delay;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;async_log::span;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;span!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;level I&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;beep&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;;
&lt;&#x2F;span&gt;&lt;span&gt;    info!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;look at this value, x={}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, x);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    span!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;level II&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; y = &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;boop&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;;
&lt;&#x2F;span&gt;&lt;span&gt;        Delay::new(Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;)).await; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; wait for 3 secs
&lt;&#x2F;span&gt;&lt;span&gt;        info!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;another nice value, y={}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, y);
&lt;&#x2F;span&gt;&lt;span&gt;    })
&lt;&#x2F;span&gt;&lt;span&gt;})
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;Log&lt;&#x2F;code&gt; implementation extends all existing &lt;code&gt;log&lt;&#x2F;code&gt; macros with asynchronous
information. This means that &lt;strong&gt;no existing call to &lt;code&gt;log&lt;&#x2F;code&gt; need to be changed&lt;&#x2F;strong&gt;, all
that&#x27;s needed is to wrap an existing logger (such as &lt;code&gt;env-logger&lt;&#x2F;code&gt;) you&#x27;re using
in &lt;code&gt;async-log&lt;&#x2F;code&gt; to add async logging capabilities.&lt;&#x2F;p&gt;
&lt;p&gt;Wrapping an existing logger is relatively straightforward:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Setup env_logger
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; logger = env_logger::Builder::new()
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span&gt;(None, log::LevelFilter::Trace)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;build&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Add async logging capabilities
&lt;&#x2F;span&gt;&lt;span&gt;async_log::Logger::wrap(logger, || &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;*get the task id here*&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;start&lt;&#x2F;span&gt;&lt;span&gt;(log::LevelFilter::Trace)?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Currently we insert &lt;code&gt;key=value&lt;&#x2F;code&gt; string literals into the log string. But once
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang-nursery&#x2F;log&#x2F;issues&#x2F;328&quot;&gt;&lt;code&gt;key-value&lt;&#x2F;code&gt; logging&lt;&#x2F;a&gt;
stabilizes, we&#x27;ll switch to support that natively. This is similar to how &lt;code&gt;slog&lt;&#x2F;code&gt;
intends to switch.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-are-spans-built&quot;&gt;How are spans built?&lt;&#x2F;h2&gt;
&lt;p&gt;A span is a pair of messages. One is emitted at the start of an operation, and
the other is emitted at the end of the operation. If we add timestamps to when
each message was sent, we&#x27;re able to determine how long operations take. Or
determine which operations never finished.&lt;&#x2F;p&gt;
&lt;p&gt;In &lt;code&gt;async-log&lt;&#x2F;code&gt; each span is annotated with a &lt;code&gt;span_mark&lt;&#x2F;code&gt; message:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;span_mark=start&lt;&#x2F;code&gt; marks the start of a span&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;span_mark=end&lt;&#x2F;code&gt; marks the end of a span&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;code&gt;async-log&lt;&#x2F;code&gt; itself does not specify a logging format, it only provides the
ascriptions required to build asynchronous loggers. However when &lt;code&gt;async-log&lt;&#x2F;code&gt; is
instantiated, and none of metadata is consumed, a typical log will look like
this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;runtime::fs::read_to_string, span_mark=start, path=&#x2F;tmp&#x2F;foob, task_id=7, thread_id=8
&lt;&#x2F;span&gt;&lt;span&gt;runtime::fs::read_to_string, span_mark=end, path=&#x2F;tmp&#x2F;foob, task_id=7, thread_id=8
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;annotating-functions&quot;&gt;Annotating functions&lt;&#x2F;h2&gt;
&lt;p&gt;One of the most common actions performed with async logging is to annotate
specific functions. For example there might be a method that calls to a
database, and you&#x27;d like to instrument. Or a method that &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;fd-lock&#x2F;1.1.0&#x2F;fd_lock&#x2F;&quot;&gt;locks a file&lt;&#x2F;a&gt; for
exclusive access.&lt;&#x2F;p&gt;
&lt;p&gt;For this reason we provide a convenient &lt;code&gt;#[instrument]&lt;&#x2F;code&gt; macro that allows
instrumenting calls to functions. All that&#x27;s required is adding the attribute to
the top of the method, and its internals will be wrapped in a &lt;code&gt;span!&lt;&#x2F;code&gt;, the
file name, method name, and arguments will be logged:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;async_log&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;instrument&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;inner&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;y&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    info!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;another nice value, y={}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, y);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;inner&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;boop&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;examples&#x2F;trace.rs#inner, arg_0=boop, span_mark=start, task_id=0, thread_id=1
&lt;&#x2F;span&gt;&lt;span&gt;examples&#x2F;trace.rs#inner, span_mark=end, task_id=0, thread_id=1
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;what-about-distributed-tracing&quot;&gt;What about distributed tracing?&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;ve been thinking hard about distributed tracing. The reality is that there
are no silver bullets, and while specifications &lt;a href=&quot;https:&#x2F;&#x2F;w3c.github.io&#x2F;trace-context&#x2F;&quot;&gt;are being worked on&lt;&#x2F;a&gt;,
implementations are unfortunately still mostly vendor specific.&lt;&#x2F;p&gt;
&lt;p&gt;However, &lt;code&gt;async-log&lt;&#x2F;code&gt; is designed as a foundational building piece for
distributed tracing. All information needed to trace individual functions can be
extracted from the &lt;code&gt;log::Log&lt;&#x2F;code&gt; provider.&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re an APM vendor that would like to provide a transport for Rust and is
interested the work we&#x27;re doing, we&#x27;d love to hear how we can help you succeed!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-next&quot;&gt;What&#x27;s next?&lt;&#x2F;h2&gt;
&lt;p&gt;The rustasync organization is mostly interested in providing standards based
approaches. But also likes to experiment with novel approaches to make Rust, and
in turn technology in general, more accessible for a wider range of people.&lt;&#x2F;p&gt;
&lt;p&gt;Some of the areas we&#x27;re looking to explore include creating flame graphs from
log data (we&#x27;re almost there!) and hooking into tracing protocols. In particular
&lt;a href=&quot;https:&#x2F;&#x2F;www.perfetto.dev&#x2F;#&#x2F;&quot;&gt;Google&#x27;s Perfetto&lt;&#x2F;a&gt; and &lt;code&gt;chrome:&#x2F;&#x2F;tracing&lt;&#x2F;code&gt; seem of
interest. We also have some other ideas we for visualization experiments, so
stay tuned for more in the future!&lt;&#x2F;p&gt;
&lt;p&gt;Like we said ealier, &lt;code&gt;async-trace&lt;&#x2F;code&gt; is but a building block of a wider tracing
story. There is much work to be done to provide varying transports, standards,
and integrations. If this sounds interesting to you, come join us during our
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustasync&#x2F;team&#x2F;issues&#x2F;131&quot;&gt;weekly, open meetings&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we introduce the &lt;code&gt;async-log&lt;&#x2F;code&gt; crate which extends the standard &lt;code&gt;log&lt;&#x2F;code&gt;
crate with asynchronous tracing functionality. The crate introduces a new
&lt;code&gt;span!&lt;&#x2F;code&gt; macro to create pairs of log points, and annotates each log call with a
task id to provide asynchronous tracing.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;re particularly excited for this crate because it&#x27;s a working example of a
possible extension to &lt;code&gt;log&lt;&#x2F;code&gt; that would make it work in asynchronous contexts,
without a need to update any of the existing calls to the &lt;code&gt;log&lt;&#x2F;code&gt; macros. In
addition we think the &lt;code&gt;instrument!&lt;&#x2F;code&gt; attribute will make it very convenient for
people to trace their functions using spans.&lt;&#x2F;p&gt;
&lt;p&gt;We hope you enjoy &lt;code&gt;async-log&lt;&#x2F;code&gt;. You can check out the project on
&lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;async-log&quot;&gt;crates.io&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;async-log&quot;&gt;docs.rs&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustasync&#x2F;async-log&quot;&gt;github&lt;&#x2F;a&gt;. Thanks for reading, and have a
great weekend!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Stjepan Glavina, Alex Crichton, and Ferrous Systems for the input and
refinement of &lt;code&gt;async-log&lt;&#x2F;code&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>std time</title>
            <pubDate>Tue, 25 Jun 2019 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/std-time/</link>
            <guid>https://blog.yoshuawuyts.com/std-time/</guid>
            <description>&lt;p&gt;Over the past month we&#x27;ve been hard at work to add &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;runtime&#x2F;0.3.0-alpha.5&#x2F;runtime&#x2F;time&#x2F;index.html&quot;&gt;&lt;code&gt;time&lt;&#x2F;code&gt; support&lt;&#x2F;a&gt; to the
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;runtime&#x2F;&quot;&gt;Runtime&lt;&#x2F;a&gt; crate. One of the things we&#x27;ve had to think about has been examples.
Which means we&#x27;ve had a chance to become intimately familiar with the good and
less good parts of the &lt;code&gt;std::time&lt;&#x2F;code&gt; API.&lt;&#x2F;p&gt;
&lt;p&gt;In this post we&#x27;ll look at the &lt;code&gt;std::time&lt;&#x2F;code&gt; API, and some of the proposed
changes to smooth things out a bit. Also disclaimer: I&#x27;ve been involved with
these proposals, hehe.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;time-types&quot;&gt;Time Types&lt;&#x2F;h2&gt;
&lt;p&gt;A quick refresher on what&#x27;s inside &lt;code&gt;std::time&lt;&#x2F;code&gt;. There are two types you need to
know about: &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;time&#x2F;struct.Duration.html&quot;&gt;&lt;code&gt;Duration&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;time&#x2F;struct.Instant.html&quot;&gt;&lt;code&gt;Instant&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. An &lt;code&gt;Instant&lt;&#x2F;code&gt; represents a &lt;em&gt;specific&lt;&#x2F;em&gt;
point in time. A &lt;code&gt;Duration&lt;&#x2F;code&gt; is a &lt;em&gt;relative&lt;&#x2F;em&gt; time offset. This is different from
some languages which only have a single time type. Personally I quite like
Rust&#x27;s approach of having two.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s put the time types together to first get the current timestamp. Then
sleep the thread for 2 seconds. And finally print how much time has passed.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::time::{Duration, Instant};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::thread::sleep;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; now = Instant::now();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;sleep&lt;&#x2F;span&gt;&lt;span&gt;(Duration::from_secs(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span&gt;println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, now.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;elapsed&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_secs&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;creating-durations&quot;&gt;Creating Durations&lt;&#x2F;h2&gt;
&lt;p&gt;As we&#x27;ve seen before, durations can be created using
&lt;code&gt;Duration::from_secs(n)&lt;&#x2F;code&gt;. This works well, but is rather verbose. Not only do
we have to import two layers deep, we also need to remember the name of the
method. All in all it takes some getting used to.&lt;&#x2F;p&gt;
&lt;p&gt;Which is why in
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;57391&quot;&gt;rust-lang&#x2F;rust#57391&lt;&#x2F;a&gt;
there&#x27;s a proposal to add constants to the time module. These constants would
represent a single unit of time, which could then be used for addition,
substraction and multiplication. E.g. 5 milliseconds is 5 times the
millisecond constant.&lt;&#x2F;p&gt;
&lt;p&gt;The exact API is still undecided. But I think it would be nice if the APIs
were brief, and exposed directly under &lt;code&gt;std::time&lt;&#x2F;code&gt;. This would allow us to
rewrite our example as:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::time::Instant;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::thread::sleep;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; now = Instant::now();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;sleep&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;* time::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;SEC&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, now.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;elapsed&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_secs&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;creating-instants&quot;&gt;Creating Instants&lt;&#x2F;h2&gt;
&lt;p&gt;Just like creating &lt;code&gt;Duration&lt;&#x2F;code&gt;s can likely be simplified, so can creating
&lt;code&gt;Instant&lt;&#x2F;code&gt;s. The most common way of creating an &lt;code&gt;Instant&lt;&#x2F;code&gt; is by calling
&lt;code&gt;Instant::now&lt;&#x2F;code&gt;. This too has the problem that we need to remember the exact
type, and call two layers deep into the &lt;code&gt;std&lt;&#x2F;code&gt; hierarchy.&lt;&#x2F;p&gt;
&lt;p&gt;Which is why
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;62114&quot;&gt;rust-lang&#x2F;rust#62114&lt;&#x2F;a&gt;
proposes to add a &lt;code&gt;time::now&lt;&#x2F;code&gt; method. This behaves the same as
&lt;code&gt;time::Instant::now&lt;&#x2F;code&gt;, but should be more pleasant to use. An example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::{time, thread};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; now = time::now();
&lt;&#x2F;span&gt;&lt;span&gt;thread::sleep(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;* time::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;SEC&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, now.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;elapsed&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_secs&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;debug-durations&quot;&gt;Debug Durations&lt;&#x2F;h2&gt;
&lt;p&gt;One of the first gotchas you might experience when dealing with time in Rust
is that you cannot simply print a &lt;code&gt;Duration&lt;&#x2F;code&gt;. If you&#x27;re like me, you&#x27;ll run
into this, and after some searching find out that you need to specify a
resolution before you can print. E.g. &lt;code&gt;dur.as_secs&lt;&#x2F;code&gt; or &lt;code&gt;dur.as_millis&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This is not great because if you&#x27;re doing &lt;em&gt;exploratory&lt;&#x2F;em&gt; programming and&#x2F;or
debugging, you may not know the resolution up front. Which means you might
need a few tries to find the right resolution. Which isn&#x27;t a dealbreaker, but
it takes speed out of the process.&lt;&#x2F;p&gt;
&lt;p&gt;Instead it would be nice if we could print &lt;code&gt;Duration&lt;&#x2F;code&gt;s (and &lt;code&gt;Instant&lt;&#x2F;code&gt;s for
that matter), where they would provide data for &lt;em&gt;all&lt;&#x2F;em&gt; resolutions it
encapsulates.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;Duration {
&lt;&#x2F;span&gt;&lt;span&gt;    secs: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    millis: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;6225&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    micros: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;6224768&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    nanos: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;6224767054&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Perhaps we might also need a pretty-printed version of this. E.g. print
&lt;code&gt;6.225 secs&lt;&#x2F;code&gt; as the &lt;code&gt;Display&lt;&#x2F;code&gt; impl. I&#x27;m not sure whether that&#x27;s acceptable
for a stdlib extension, but I sure know that it would make debugging time a
lot easier.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, let&#x27;s apply this to our example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::{time, thread};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; now = time::now();
&lt;&#x2F;span&gt;&lt;span&gt;thread::sleep(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;* time::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;SEC&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;dbg!(now.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;elapsed&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve talked about the &lt;code&gt;std::time&lt;&#x2F;code&gt; module, and some of the
changes that could be made to smooth out the workflow.&lt;&#x2F;p&gt;
&lt;p&gt;I hope this was a useful insight into how the &lt;code&gt;std::time&lt;&#x2F;code&gt; module can be
improved. I figured I&#x27;d write this post because I spent some time earlier
today filing an issue, and thought sharing an overarching vision might be
nice.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks for reading all, and hope you have a lovely (non-scorched) week!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>rust streams</title>
            <pubDate>Thu, 20 Jun 2019 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/rust-streams/</link>
            <guid>https://blog.yoshuawuyts.com/rust-streams/</guid>
            <description>&lt;p&gt;As Rust&#x27;s async story is evolving, so is Rust&#x27;s streaming story. In this post
we&#x27;ll take a look at how Rust&#x27;s streaming model works, how to use it
effectively, and where things are heading in the future.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-stream-traits&quot;&gt;The stream traits&lt;&#x2F;h2&gt;
&lt;p&gt;In synchronous Rust, the core streaming abstraction is that of &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.Iterator.html&quot;&gt;&lt;code&gt;Iterator&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. It
provides a way of yielding items in a sequence, and blocks in between.
Composition is done by passing iterators into the constructors of other
iterators, allowing us to plumb things together without much fanfare.&lt;&#x2F;p&gt;
&lt;p&gt;In asynchronous Rust the core streaming abstraction is &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-preview&#x2F;0.3.0-alpha.16&#x2F;futures&#x2F;stream&#x2F;trait.Stream.html&quot;&gt;&lt;code&gt;Stream&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. It behaves
very similar to &lt;code&gt;Iterator&lt;&#x2F;code&gt;, but instead of blocking between each item yield, it
allows other tasks to run while it waits.&lt;&#x2F;p&gt;
&lt;p&gt;In addition async Rust has counterparts to the synchronous &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;io&#x2F;trait.Read.html&quot;&gt;&lt;code&gt;Read&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;io&#x2F;trait.Write.html&quot;&gt;&lt;code&gt;Write&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; in the form of &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-preview&#x2F;0.3.0-alpha.16&#x2F;futures&#x2F;io&#x2F;trait.AsyncRead.html&quot;&gt;&lt;code&gt;AsyncRead&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-preview&#x2F;0.3.0-alpha.16&#x2F;futures&#x2F;io&#x2F;trait.AsyncWrite.html&quot;&gt;&lt;code&gt;AsyncWrite&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. The purpose of these
traits is to represent unparsed bytes, often coming directly from the IO layer
(such as from sockets or files).&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;runtime::fs::File;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; f = file::create(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;foo.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; create a file
&lt;&#x2F;span&gt;&lt;span&gt;f.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write_all&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello world&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; write data to the file (AsyncWrite)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; f = file::open(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;foo.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).await?; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; open a file
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; buffer = Vec::new();          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; init the buffer to read the data into
&lt;&#x2F;span&gt;&lt;span&gt;f.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_to_end&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; buffer).await?;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; read the whole file (AsyncRead)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Rust streams have some of the best features of other languages. For example:
they sidestep inheritance problems as seen in &lt;a href=&quot;https:&#x2F;&#x2F;nodejs.org&#x2F;api&#x2F;stream.html#stream_class_stream_duplex&quot;&gt;Node.js&#x27;s Duplex
streams&lt;&#x2F;a&gt; by
leveraging Rust&#x27;s trait system. But they also implement backpressure and lazy
iteration, improving their efficiency. And on top of that, Rust streams allow
asynchronous iteration using the same type.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s a lot to like about Rust streams, even though there are still some kinks
to be sorted out.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;streams-and-roles&quot;&gt;Streams and roles&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s start off by enumerating the kinds of streams that can be expressed in
a typical system:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;source:&lt;&#x2F;strong&gt; a stream that can produce data&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;sink:&lt;&#x2F;strong&gt; a stream that can consume data&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;through:&lt;&#x2F;strong&gt; a stream that consumes data, operates on it, and then produces
new data&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;duplex:&lt;&#x2F;strong&gt; a stream can produce data, and independently can also consume
data&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Establishing common terminology is useful because Rust&#x27;s stream traits don&#x27;t
map 1:1 to these roles. In fact, each of Rust&#x27;s stream traits can be used to
fill many different roles. Here&#x27;s an overview of which roles each trait can
take part in:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;Source&lt;&#x2F;th&gt;&lt;th&gt;Sink&lt;&#x2F;th&gt;&lt;th&gt;Through&lt;&#x2F;th&gt;&lt;th&gt;Duplex&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;AsyncRead&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Yes&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;em&gt;No&lt;&#x2F;em&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Yes&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Yes&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;AsyncWrite&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;em&gt;No&lt;&#x2F;em&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Yes&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;em&gt;No&lt;&#x2F;em&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Yes&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Stream&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Yes&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;em&gt;No&lt;&#x2F;em&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Yes&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;em&gt;No&lt;&#x2F;em&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;There&#x27;s quite a bit to unpack here. Let&#x27;s dig in!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;duplex&quot;&gt;duplex&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;duplex&lt;&#x2F;code&gt; is always implemented using &lt;code&gt;AsyncRead&lt;&#x2F;code&gt; + &lt;code&gt;AsyncWrite&lt;&#x2F;code&gt;. This is not
unlike other languages. A key difference, however, is that using Rust&#x27;s trait
system we can evade multiple inheritance problems that plague some other
languages. Examples of &lt;code&gt;duplex&lt;&#x2F;code&gt; streams include sockets and files.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;through&quot;&gt;through&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;through&lt;&#x2F;code&gt; streams are implemented using either &lt;code&gt;AsyncRead&lt;&#x2F;code&gt; or &lt;code&gt;Stream&lt;&#x2F;code&gt;. Data
flows from one stream to the other by passing another &lt;code&gt;through&lt;&#x2F;code&gt; into its
constructor.&lt;&#x2F;p&gt;
&lt;p&gt;In Rust, the only difference between &lt;code&gt;source&lt;&#x2F;code&gt; and &lt;code&gt;through&lt;&#x2F;code&gt; is in how the
traits are used, not in the trait definitions themselves. An example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; s = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello planet&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; source  (AsyncRead)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; s = gzip::compress(s).await?;       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; through (AsyncRead)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; s = my_protocol::parse(s).await?;   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; through (Stream)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;asyncread-vs-stream&quot;&gt;asyncread vs stream&lt;&#x2F;h3&gt;
&lt;p&gt;Another point of interest is the distinction between &lt;code&gt;AsyncRead&lt;&#x2F;code&gt; and
&lt;code&gt;Stream&lt;&#x2F;code&gt;. Both kinds of streams are allowed to operate on bytes. But the
difference is that &lt;code&gt;AsyncRead&lt;&#x2F;code&gt; is a &lt;em&gt;byte stream&lt;&#x2F;em&gt; that operates on borrowed
data. While &lt;code&gt;Stream&lt;&#x2F;code&gt; is an &lt;em&gt;object stream&lt;&#x2F;em&gt; that operates on owned data. This
is to say that &lt;code&gt;Stream&lt;&#x2F;code&gt; can operate on any kind of data, not only bytes.&lt;&#x2F;p&gt;
&lt;p&gt;While both &lt;code&gt;AsyncRead&lt;&#x2F;code&gt; and &lt;code&gt;Stream&lt;&#x2F;code&gt; can operate on bytes, &lt;code&gt;AsyncRead&lt;&#x2F;code&gt; yields
&lt;em&gt;unparsed data&lt;&#x2F;em&gt;, while &lt;code&gt;Stream&lt;&#x2F;code&gt; yields &lt;em&gt;parsed data&lt;&#x2F;em&gt;. The difference is that
with &lt;code&gt;Stream&lt;&#x2F;code&gt; each item yielded can generally be turned into a valid message
on its own. While with &lt;code&gt;AsyncRead&lt;&#x2F;code&gt; it may be the case we need to request more
data.&lt;&#x2F;p&gt;
&lt;p&gt;Examples of &lt;code&gt;AsyncRead&lt;&#x2F;code&gt; include files, sockets, and HTTP bodies. Examples of
&lt;code&gt;Stream&lt;&#x2F;code&gt; include &lt;a href=&quot;http:&#x2F;&#x2F;ndjson.org&#x2F;&quot;&gt;ndjson lines&lt;&#x2F;a&gt;, and protobuf messages.&lt;&#x2F;p&gt;
&lt;p&gt;The relationship between &lt;code&gt;AsyncRead&lt;&#x2F;code&gt; and &lt;code&gt;Stream&lt;&#x2F;code&gt; is equivalent to the
relationship between stdlib&#x27;s &lt;code&gt;Read&lt;&#x2F;code&gt; and &lt;code&gt;Iterator&lt;&#x2F;code&gt; traits. In the following
example we convert arbitrary amount of bytes into separate lines of bytes
using &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;io&#x2F;trait.BufRead.html#method.split&quot;&gt;&lt;code&gt;split&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. We&#x27;ve marked each line with the traits and yield types:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::io;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; f = io::File::open(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;foo.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Read&amp;lt;[u8]&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; f = io::BufReader::new(f);      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Read&amp;lt;[u8]&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; buf in f.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;) {         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Iterator&amp;lt;[u8]&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, buf);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Same data types. Different traits.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-preview&#x2F;0.3.0-alpha.16&#x2F;futures&#x2F;io&#x2F;trait.AsyncReadExt.html#method.split&quot;&gt;&lt;code&gt;AsyncRead.split&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; does something radically different, so this
example can&#x27;t be directly copied over yet (more on what &lt;code&gt;split&lt;&#x2F;code&gt; does later).
So don&#x27;t try and write this in async Rust quite yet.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sinks&quot;&gt;sinks&lt;&#x2F;h3&gt;
&lt;p&gt;The way streams work is that at the end of a stream pipeline, there&#x27;s a
&lt;code&gt;sink&lt;&#x2F;code&gt; or iterator requesting items from the streams. This means that the
stream pipeline will only yield data if it&#x27;s requested for. This is commonly
referred to as &quot;lazy iteration&quot;, or &quot;streams with backpressure&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Currently there&#x27;s no dedicated syntax to loop through streams. Instead it&#x27;s
recommended to use a &lt;code&gt;while let Some&lt;&#x2F;code&gt; loop:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; stream = my_protocol::parse(f).await?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(item) = stream.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().await {
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, item);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now that we have a slightly better picture of how Rust&#x27;s traits related to
streaming concepts, we&#x27;re ready to take a look at how to create streaming
pipelines.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pipelines&quot;&gt;Pipelines&lt;&#x2F;h2&gt;
&lt;p&gt;One of the staples of streams-based programming is being able to compose
streams together. In shell you can pipe programs together using &lt;code&gt;|&lt;&#x2F;code&gt;, and in
Node.js you can do the same using &lt;code&gt;.pipe&lt;&#x2F;code&gt;. A typical shell example looks like
this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; cat foo.txt | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;gzip &lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; foo.txt.gz
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The example above reads data from &lt;code&gt;foo.txt&lt;&#x2F;code&gt;, pipes it through &lt;code&gt;gzip&lt;&#x2F;code&gt; to
compress the data, and writes the result back out to a new file.&lt;&#x2F;p&gt;
&lt;p&gt;Rust streams have a very similar model. In fact we could imagine the same
code being written in Rust as:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;runtime::fs::File;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;File::open(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;foo.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;| gzip::compress(s))
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;| word_count::bytes(s))
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;| s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;copy_into&lt;&#x2F;span&gt;&lt;span&gt;(File::create(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;foo.txt.gz&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)))
&lt;&#x2F;span&gt;&lt;span&gt;    .await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This code example won&#x27;t run today because not all packages exist yet. But it
illustrates quite well how Rust&#x27;s streams work in practice. We can express the
pipeline abstractly as follows:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;┌───────────┐   ┌───────────┐   ┌────────────┐
&lt;&#x2F;span&gt;&lt;span&gt;│ AsyncRead │──&amp;gt;│ AsyncRead │──&amp;gt;│ AsyncWrite │
&lt;&#x2F;span&gt;&lt;span&gt;└───────────┘   └───────────┘   └────────────┘
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Data goes from the source file, through the compressor into the destination
file. Different pipelines will use different combinations of &lt;code&gt;AsyncRead&lt;&#x2F;code&gt; and
&lt;code&gt;Sink&lt;&#x2F;code&gt;. But in all patterns it&#x27;s going to be common to pass the last stream
down to the next constructor, until we reach a sink.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;piping-duplex-streams&quot;&gt;Piping duplex streams&lt;&#x2F;h2&gt;
&lt;p&gt;When duplex streams are involved, the streaming model gets a little trickier.
Let&#x27;s pretend we&#x27;re opening a socket that implements &lt;code&gt;AsyncRead&lt;&#x2F;code&gt; + &lt;code&gt;AsyncWrite&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; sock = Socket::new(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;localhost:3000&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;dbg!(sock) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; implements AsyncRead + AsyncWrite
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We want to read data from the socket, operate on each value, and write data back
to the socket. In Rust this would get us in trouble because we can&#x27;t hold a
mutable reference to the same value in two places. So duplex streams have a
convenient &lt;code&gt;split&lt;&#x2F;code&gt; method to split the socket into a reader and writer half:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; sock = Socket::new(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;localhost:3000&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(reader, writer) = &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; sock.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;piping-asyncread-to-asyncwrite&quot;&gt;Piping AsyncRead to AsyncWrite&lt;&#x2F;h2&gt;
&lt;p&gt;In the example above, the &lt;code&gt;Socket&lt;&#x2F;code&gt; duplex is both a &lt;em&gt;source&lt;&#x2F;em&gt;, and a &lt;em&gt;sink&lt;&#x2F;em&gt;.
Neither of these methods wraps another stream. And sometimes we&#x27;re only
interested in the read or the write half of the stream. Which is why it&#x27;s
uncommon for Duplex streams to take other streams in their constructor.&lt;&#x2F;p&gt;
&lt;p&gt;So how do we write data to it?&lt;&#x2F;p&gt;
&lt;p&gt;Well, Rust conveniently has a &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-preview&#x2F;0.3.0-alpha.16&#x2F;futures&#x2F;io&#x2F;trait.AsyncReadExt.html#method.copy_into&quot;&gt;&lt;code&gt;copy_into&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; combinator for this exact purpose.
It takes data from an &lt;code&gt;AsyncRead&lt;&#x2F;code&gt;, and writes it to an &lt;code&gt;AsyncWrite&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; sock = Socket::new(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;localhost:3000&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(reader, writer) = &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; sock.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;reader.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;copy_into&lt;&#x2F;span&gt;&lt;span&gt;(writer).await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;piping-stream-to-asyncwrite&quot;&gt;Piping Stream to AsyncWrite&lt;&#x2F;h2&gt;
&lt;p&gt;If we want to write data from a &lt;code&gt;Stream&lt;&#x2F;code&gt; to an &lt;code&gt;AsyncWrite&lt;&#x2F;code&gt;, things become quite
a bit tricky. First off our &lt;code&gt;Stream&lt;&#x2F;code&gt; should output bytes (&lt;code&gt;&amp;amp;[u8]&lt;&#x2F;code&gt; or &lt;code&gt;Vec&amp;lt;u8&amp;gt;&lt;&#x2F;code&gt;),
because IO devices can only read bytes.&lt;&#x2F;p&gt;
&lt;p&gt;But more importantly: there&#x27;s currently no &lt;code&gt;copy_into&lt;&#x2F;code&gt; combinator available! But
we can work around that by converting from &lt;code&gt;Stream&lt;&#x2F;code&gt; into &lt;code&gt;AsyncRead&lt;&#x2F;code&gt;, and then
calling &lt;code&gt;copy_into&lt;&#x2F;code&gt; on that:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;stream
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(io::Result::Ok)  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; convert each `Vec&amp;lt;u8&amp;gt;` to `Result&amp;lt;Vec&amp;lt;u8&amp;gt;&amp;gt;`
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;into_async_read&lt;&#x2F;span&gt;&lt;span&gt;()    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; convert the stream to `AsyncRead`
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;copy_into&lt;&#x2F;span&gt;&lt;span&gt;(writer)    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; copy the data to the sink
&lt;&#x2F;span&gt;&lt;span&gt;    .await?;              &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; start the pipeline
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Currently this code does suffer from &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang-nursery&#x2F;futures-rs&#x2F;issues&#x2F;1659&quot;&gt;a double buffering
bug&lt;&#x2F;a&gt;, which makes
it less efficient than it could be. But what would likely work best here is if
&lt;code&gt;copy_into&lt;&#x2F;code&gt; &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang-nursery&#x2F;futures-rs&#x2F;issues&#x2F;1661&quot;&gt;would work for &lt;code&gt;Stream&lt;&#x2F;code&gt;
too&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;stream.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;copy_into&lt;&#x2F;span&gt;&lt;span&gt;(writer).await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;handling-errors&quot;&gt;Handling errors&lt;&#x2F;h2&gt;
&lt;p&gt;One of the biggest mistakes Node.js made when it introduced streams, was that
&lt;code&gt;pipe&lt;&#x2F;code&gt; doesn&#x27;t forward errors. Luckily in Rust streams this is solved because of
how streams are wrapped in constructors. This means that streams automatically
forward errors, and pipelines handle them.&lt;&#x2F;p&gt;
&lt;p&gt;The only difficulty with error handling is that the error kinds need to line up.
This can be particularly tricky when creating pipelines that include errors
other than &lt;code&gt;io::Error&lt;&#x2F;code&gt;. But the ecosystem is still young, and patterns are still
emerging, so it shouldn&#x27;t be surprising not everything is streamlined quite yet.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;writing-codecs&quot;&gt;writing codecs&lt;&#x2F;h2&gt;
&lt;p&gt;It&#x27;s common for parser protocols be split into an &lt;em&gt;encoder&lt;&#x2F;em&gt; and &lt;em&gt;decoder&lt;&#x2F;em&gt; half.
Encoders convert structs to sequences of bytes. And decoders convert bytes into
structs. This can easily be modeled in Rust:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; The type we&amp;#39;re converting to and from.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;MyFrame;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Convert frames to bytes.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Encoder;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Encoder {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Take a stream of frames, and return a stream of bytes.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;encode&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;stream&lt;&#x2F;span&gt;&lt;span&gt;: impl Stream&amp;lt;Item = MyFrame&amp;gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Stream &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Encoder {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item = Result&amp;lt;Vec&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;, Error&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Convert bytes to frames.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span&gt;Decoder;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Decoder {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Take a stream of bytes, and return a stream of frames.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;decode&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;reader&lt;&#x2F;span&gt;&lt;span&gt;: impl AsyncRead) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Stream &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;Decoder {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Item = Result&amp;lt;MyFrame, Error&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There exist specialized crates that are meant to assist in the creation of
codecs. But in practice codecs are mostly a design pattern, and the easiest way
to write them is using the standard stream traits directly.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;note: depending on your use case you might need to perform some internal
buffering when writing decoders. But all that requires is a good (ring)buffer
abstraction, and there&#x27;s a variety on crates.io.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ad-hoc-streams-using-combinators&quot;&gt;ad-hoc streams using combinators&lt;&#x2F;h2&gt;
&lt;p&gt;Sometimes you want to quickly operate on the output of a stream. Whether it&#x27;s
filtering out results you&#x27;re not interested in, concatenating items, or doing a
quick count. Streams combinators allow you to perform these tasks with little
overhead.&lt;&#x2F;p&gt;
&lt;p&gt;Say we wanted to read data from a file, and split it by newline. The &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-preview&#x2F;0.3.0-alpha.16&#x2F;futures&#x2F;io&#x2F;trait.AsyncBufReadExt.html#method.lines&quot;&gt;&lt;code&gt;lines&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
combinators provides that:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; sock = Socket::new(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;localhost:3000&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(reader, _) = &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; sock.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; This is returns a stream of `String`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; lines = reader.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;lines&lt;&#x2F;span&gt;&lt;span&gt;().await?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now what if we wanted to parse those lines using &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;serde&#x2F;1.0.92&#x2F;serde&#x2F;&quot;&gt;&lt;code&gt;serde&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;? Cue the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-preview&#x2F;0.3.0-alpha.16&#x2F;futures&#x2F;future&#x2F;trait.FutureExt.html#method.map&quot;&gt;&lt;code&gt;map&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
combinator:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; sock = Socket::new(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;localhost:3000&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(reader, _) = &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; sock.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(Deserialize)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Pet {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: String,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; This returns a stream of `Result&amp;lt;Pet&amp;gt;`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; pet_stream = reader
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;lines&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;line&lt;&#x2F;span&gt;&lt;span&gt;| serde_json::parse::&amp;lt;Pet&amp;gt;(line));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Another interesting fact to point out is that &lt;code&gt;Vec&amp;lt;u8&amp;gt;&lt;&#x2F;code&gt; implements both
&lt;code&gt;AsyncRead&lt;&#x2F;code&gt; and &lt;code&gt;AsyncWrite&lt;&#x2F;code&gt;, which means that if you want to concatenate all
values of a stream, it&#x27;s possible to use a buffer directly for that.&lt;&#x2F;p&gt;
&lt;p&gt;There are probably many more combinators that could be added, and patterns to be
explored. But the core mechanics of Rust&#x27;s streams feel really solid, and more
combinators can be added as we grow the ecosystem.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-we-do-not-talk-about-the-sink-trait&quot;&gt;Why we do not talk about the sink trait&lt;&#x2F;h2&gt;
&lt;p&gt;Surprise! There&#x27;s another trait you should know about. Its name is &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-preview&#x2F;0.3.0-alpha.16&#x2F;futures&#x2F;sink&#x2F;trait.Sink.html&quot;&gt;&lt;code&gt;Sink&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, and
it&#x27;s the odd one out in the lot. It&#x27;s not just confusing to say out loud (are we
talking about &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;marker&#x2F;trait.Sync.html&quot;&gt;&lt;code&gt;Sync&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; or &lt;code&gt;Sink&lt;&#x2F;code&gt;?), but the trait itself is quite out there.
Take a look at the definition:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Sink&amp;lt;Item&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;SinkError;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll_ready&lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; Contex
&lt;&#x2F;span&gt;&lt;span&gt;    ) -&amp;gt; Poll&amp;lt;Result&amp;lt;(), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;SinkError&amp;gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;start_send&lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;item&lt;&#x2F;span&gt;&lt;span&gt;: Item
&lt;&#x2F;span&gt;&lt;span&gt;    ) -&amp;gt; Result&amp;lt;(), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;SinkError&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll_flush&lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; Context
&lt;&#x2F;span&gt;&lt;span&gt;    ) -&amp;gt; Poll&amp;lt;Result&amp;lt;(), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;SinkError&amp;gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll_close&lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; Context
&lt;&#x2F;span&gt;&lt;span&gt;    ) -&amp;gt; Poll&amp;lt;Result&amp;lt;(), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;SinkError&amp;gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s right. Whenever you implement &lt;code&gt;Sink&lt;&#x2F;code&gt; you need to implement 4 methods, 1
associated type, and 1 generic parameter. Oh and also a mandatory internal
buffer. Because all those methods in the trait definition are hooks into a very
specific lifecycle. Where the only way to move data through that cycle is by
temporarily storing data internally, and yielding it again at a later point.&lt;&#x2F;p&gt;
&lt;p&gt;Maybe you&#x27;ve caught on to it, but &lt;code&gt;Sink&lt;&#x2F;code&gt; is not simple. Its &lt;em&gt;raison d&#x27;être&lt;&#x2F;em&gt; is
to be a typed counterpart to &lt;code&gt;AsyncWrite&lt;&#x2F;code&gt;. It usually wraps a writer in its
constructor, and then serializes types into it.&lt;&#x2F;p&gt;
&lt;p&gt;On paper this might sound appealing. But in practice nobody dares write this
monster of a trait without heavy-handed help from crates.io. Which begs the
question if this amount of complexity is actually worth it. And the answer increasingly seems to be a resounding &lt;em&gt;&quot;no&quot;&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Sink&lt;&#x2F;code&gt; doesn&#x27;t bring anything to the table that can&#x27;t be solved more
elegantly and with less ceremony using the 3 standard stream traits. So save
yourself some trouble, and don&#x27;t bother with &lt;code&gt;Sink&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-next&quot;&gt;What&#x27;s next?&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;async-iteration-syntax&quot;&gt;async iteration syntax&lt;&#x2F;h3&gt;
&lt;p&gt;Async iteration of streams is currently possible, but it isn&#x27;t necessarily nice
to use. Most user land iteration of streams is done using &lt;code&gt;while let Some&lt;&#x2F;code&gt; loops&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; listener = TcpListener::bind(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8081&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; incoming = listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;incoming&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(conn) = incoming.await {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; conn = conn?;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;* handle connection *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;d be nicer if we could write this as a &lt;code&gt;for await&lt;&#x2F;code&gt; loop instead:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; listener = TcpListener::bind(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8081&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; conn.await? in listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;incoming&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;* handle connection *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s unclear when this will happen. But it&#x27;s definitely something worth looking
forward to!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;async-trait-streams&quot;&gt;async trait streams&lt;&#x2F;h3&gt;
&lt;p&gt;Speaking of improvements, the stream traits themselves could use some work.
Currently the traits are quite similar to the &lt;code&gt;Future&lt;&#x2F;code&gt; trait:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;AsyncRead {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;poll_read&lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;: Pin&amp;lt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cx&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; Context,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    ) -&amp;gt; Poll&amp;lt;io::Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What makes this especially tricky is the definition of &lt;code&gt;self: Pin&amp;lt;&amp;amp;mut Self&amp;gt;&lt;&#x2F;code&gt;.
This means this method is only implemented for instances of &lt;code&gt;Self&lt;&#x2F;code&gt; that are
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;pin&#x2F;index.html&quot;&gt;pinned&lt;&#x2F;a&gt;. I don&#x27;t want to bore you with all the ways &lt;em&gt;why&lt;&#x2F;em&gt; this is tricky, but
instead I want to mention that lately I&#x27;ve been hearing conversations about a
possible simplification of these traits.&lt;&#x2F;p&gt;
&lt;p&gt;In principle the stream traits don&#x27;t have anything async about them. The only
reason why they&#x27;re async is because they return futures, and might need to wait
on other futures internally. This is important, because once &lt;code&gt;async&lt;&#x2F;code&gt; is allowed
in traits directly, it seems like it would be possible to simplify the traits
significantly.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;AsyncRead {
&lt;&#x2F;span&gt;&lt;span&gt;    async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]) -&amp;gt; io::Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This would be particularly nice because it would mean &lt;code&gt;AsyncRead&lt;&#x2F;code&gt;, &lt;code&gt;AsyncWrite&lt;&#x2F;code&gt;
and &lt;code&gt;Stream&lt;&#x2F;code&gt; would be defined the exact same way as std &lt;code&gt;Read&lt;&#x2F;code&gt;, &lt;code&gt;Write&lt;&#x2F;code&gt;, and
&lt;code&gt;Iterator&lt;&#x2F;code&gt; with the only difference being the &lt;code&gt;async&lt;&#x2F;code&gt; keyword in front of the
methods.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;Read {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]) -&amp;gt; io::Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Nothing about this is sure though. But I&#x27;m cautiously optimistic about the
possibilities here.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;anonymous-streams-using-yield&quot;&gt;anonymous streams using &lt;code&gt;yield&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Speaking of improvements to how we define streams, another thing that has been
talked about is adding syntax for generators. Generators would likely use the
&lt;code&gt;yield&lt;&#x2F;code&gt; keyword, and we could imagine a stream essentially being a generator of
futures. And just like &lt;code&gt;async&#x2F;await&lt;&#x2F;code&gt; allows us to skip the boilerplate around
constructing futures, &lt;code&gt;yield&lt;&#x2F;code&gt; would give us the same for streams:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;keep_squaring&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;val&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; yield &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;       val *= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;       &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#bf616a;color:#2b303b;&quot;&gt;yield&lt;&#x2F;span&gt;&lt;span&gt; val;
&lt;&#x2F;span&gt;&lt;span&gt;   }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; val.await in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;keep_squaring&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    dbg!(val);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This one might be a lot further out though, but seems like it has the potential
to provide some welcome workflow improvements.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;zero-copy-reads-and-writes&quot;&gt;zero-copy reads and writes&lt;&#x2F;h3&gt;
&lt;p&gt;A nice feature &lt;code&gt;AsyncRead&lt;&#x2F;code&gt; and &lt;code&gt;AsyncWrite&lt;&#x2F;code&gt; have is support for vectored IO
through &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-preview&#x2F;0.3.0-alpha.16&#x2F;futures&#x2F;io&#x2F;trait.AsyncRead.html#method.poll_read_vectored&quot;&gt;&lt;code&gt;poll_read_vectored&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-preview&#x2F;0.3.0-alpha.16&#x2F;futures&#x2F;io&#x2F;trait.AsyncWrite.html#method.poll_write_vectored&quot;&gt;&lt;code&gt;poll_write_vectored&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. This allows
optimizing performance for specific applications.&lt;&#x2F;p&gt;
&lt;p&gt;A similar method that might be useful to add in the future are
&lt;code&gt;poll_read_vec&lt;&#x2F;code&gt; and &lt;code&gt;poll_write_vec&lt;&#x2F;code&gt; (perhaps under a less confusing name).
These methods would allow passing buffers directly into the methods, and
using a &lt;code&gt;mem::swap&lt;&#x2F;code&gt; trick, prevent performing one extra &lt;code&gt;memcpy&lt;&#x2F;code&gt; on every
operation. Allowing us to increase performance in certain APIs significantly,
without needing to modify the end-user API at all.&lt;&#x2F;p&gt;
&lt;p&gt;This is particularly relevant when wrapping synchronous APIs (which currently
means: almost every filesystem operation). But more importantly: it would allow
us to remove the extra overhead Rust currently has for futures based IO,
compared to using the OS APIs directly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve talked about the different kinds of async streams rust has,
discussed common patterns and pitfalls, and looked towards a possible future of
streams.&lt;&#x2F;p&gt;
&lt;p&gt;The future or Rust streams is incredibly exciting! If we can nail the ergonomics
of piping streams together, we&#x27;ll be one step closer to making Rust a great
option for the space traditionally held by scripting languages. But with Rust&#x27;s
reliability guarantees.&lt;&#x2F;p&gt;
&lt;p&gt;We hope you enjoyed reading about streams! -- have a great week!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Irina Shestak, Nemo157, David Barsky, Stjepan Glavina, and Hugh
Kennedy for reading and providing feedback, ideas, and input on the many
iterations of this post.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Paw</title>
            <pubDate>Mon, 06 May 2019 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/paw/</link>
            <guid>https://blog.yoshuawuyts.com/paw/</guid>
            <description>&lt;p&gt;Today we&#x27;re announcing &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;paw&#x2F;1.0.0&#x2F;paw&#x2F;&quot;&gt;paw&lt;&#x2F;a&gt;, a first step by the CLI Working Group to make command line applications more
first class in Rust.&lt;&#x2F;p&gt;
&lt;p&gt;We introduce a procedural macro &lt;code&gt;paw::main&lt;&#x2F;code&gt; that allows passing arguments to &lt;code&gt;fn main&lt;&#x2F;code&gt;, and a new trait
&lt;code&gt;ParseArgs&lt;&#x2F;code&gt; that must be implemented by the arguments to &lt;code&gt;main&lt;&#x2F;code&gt;. This allows passing not only the classic
&lt;code&gt;std::env::Args&lt;&#x2F;code&gt; to &lt;code&gt;main&lt;&#x2F;code&gt; but also, for example, &lt;code&gt;structopt&lt;&#x2F;code&gt; instances.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;print_args&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;args&lt;&#x2F;span&gt;&lt;span&gt;: std::env::Args) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; arg in args {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, arg);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; cargo run&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; --example&lt;&#x2F;span&gt;&lt;span&gt; print_args -- hello world
&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;world&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;structopt&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(structopt::StructOpt)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;Args {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;address&lt;&#x2F;span&gt;&lt;span&gt;: String,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u16&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;args&lt;&#x2F;span&gt;&lt;span&gt;: Args) -&amp;gt; Result&amp;lt;(), failure::Error&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; app = tide::App::new(());
&lt;&#x2F;span&gt;&lt;span&gt;    app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;at&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(async |_| &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Hello, world!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;    app.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;serve&lt;&#x2F;span&gt;&lt;span&gt;((args.address, args.port)).await?;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; cargo run&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; --example&lt;&#x2F;span&gt;&lt;span&gt; structopt -- localhost 8080
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Our hope is that by allowing flexible passing of arguments to &lt;code&gt;fn main&lt;&#x2F;code&gt; we can make command line
parsing feel more intuitive for new Rustaceans and seasoned experts alike.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;paw-today&quot;&gt;Paw today&lt;&#x2F;h2&gt;
&lt;p&gt;What &lt;code&gt;paw&lt;&#x2F;code&gt; brings is a stepping stone to enable our vision of first-class command line parsing in
Rust. We envision a place where &lt;code&gt;ParseArgs&lt;&#x2F;code&gt; is included in stdlib, and &lt;code&gt;std::env::Args&lt;&#x2F;code&gt; implements
it out of the box. However, as a precursor to an RFC we want to polish the ergonomics and test the
usability of &lt;code&gt;paw&lt;&#x2F;code&gt; to get it right.&lt;&#x2F;p&gt;
&lt;p&gt;With &lt;code&gt;paw&lt;&#x2F;code&gt; today the &lt;code&gt;print&lt;&#x2F;code&gt; example can be written as:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;paw&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;args&lt;&#x2F;span&gt;&lt;span&gt;: paw::Args) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; arg in args {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{:?}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, arg);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This should provide a comparable experience to what a potential std experience would be like.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-does-the-trait-work&quot;&gt;How does the trait work?&lt;&#x2F;h2&gt;
&lt;p&gt;The trait has 1 method: &lt;code&gt;parse_args&lt;&#x2F;code&gt; which returns a &lt;code&gt;Result&amp;lt;Self&amp;gt;&lt;&#x2F;code&gt;. Because this must be known
at compile time, &lt;code&gt;Self&lt;&#x2F;code&gt; needs to be &lt;code&gt;Sized&lt;&#x2F;code&gt;, and we have an associated &lt;code&gt;Error&lt;&#x2F;code&gt; type too. In total
the declaration is about 4 lines, which means as far as traits go it&#x27;s quite small.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span&gt;ParseArgs: Sized {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span&gt;Error;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;parse_args&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; Result&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Error&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;paw::main&lt;&#x2F;code&gt; macro detects if the trait is implemented for the argument passed in at runtime, and then
replaces &lt;code&gt;(args: Args)&lt;&#x2F;code&gt; with &lt;code&gt;let args = Args::parse_args()&lt;&#x2F;code&gt; inside the function body. We suspect
that adding similar functionality to std would be a (relatively) small change too.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;ve introduced &lt;code&gt;paw&lt;&#x2F;code&gt;, a crate to enable arguments in main. It consists of a proc macro, trait, and
wrappers around stdlib&#x27;s &lt;code&gt;std::env::Args&lt;&#x2F;code&gt; and &lt;code&gt;std::env::ArgsOs&lt;&#x2F;code&gt; types.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;paw&lt;&#x2F;code&gt; is available on GitHub as &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-cli&#x2F;paw&quot;&gt;rust-cli&#x2F;paw&lt;&#x2F;a&gt;, and on crates.io as
&lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;paw&quot;&gt;paw&lt;&#x2F;a&gt;. Happy hacking!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;thanks&quot;&gt;Thanks&lt;&#x2F;h2&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;stjepang&#x2F;&quot;&gt;stjepang&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Dylan-DPC&quot;&gt;Dylan-DPC&lt;&#x2F;a&gt; for
help with the implementation. And all of the CLI WG for help and feedback on the API and this post.&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>graphs</title>
            <pubDate>Mon, 22 Apr 2019 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/graphs/</link>
            <guid>https://blog.yoshuawuyts.com/graphs/</guid>
            <description>&lt;ul&gt;
&lt;li&gt;You, sobbing: You can&#x27;t just point at every data structure and call it a graph.&lt;&#x2F;li&gt;
&lt;li&gt;Me: *pointing at a linked list*: graph.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;— &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;mgattozzi&#x2F;status&#x2F;960607169375850496?s=09&quot;&gt;@mgattozzi&lt;&#x2F;a&gt; (paraphrased)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Graphs are a bit of an umbrella term in the field of data structures. There are many kind of graphs,
and each has different properties. Inherently graphs are about expressing relationships, and
understanding what the relationships of a problem are can help you understand the fundamental
structure of a problem. Which in turn provides you with the right starting point to simplify a
problem.&lt;&#x2F;p&gt;
&lt;p&gt;In this post we&#x27;ll briefly go through some common graph types, their properties, and examples of
problems that can be expressed in them.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;primer&quot;&gt;Primer&lt;&#x2F;h2&gt;
&lt;p&gt;Before we dive in, it might be useful to (re-)explore some basic concepts related to graphs. Feel
free to skip this if you&#x27;re already comfortable with them, but perhaps this might be useful
regardless.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;relationships&quot;&gt;Relationships&lt;&#x2F;h3&gt;
&lt;p&gt;Any kind of relationship can be expressed as one of 3 kinds:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;1 to 1 relationship (aka &lt;code&gt;1:1&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;1 to many relationship &#x2F; many to 1 relationship (aka &lt;code&gt;1:m&lt;&#x2F;code&gt;, &lt;code&gt;m:1&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;many to many relationship (aka &lt;code&gt;m:n&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;graphs&quot;&gt;Graphs&lt;&#x2F;h3&gt;
&lt;p&gt;A graph structure is one of &quot;nodes&quot; and &quot;relationships between nodes&quot;. This is often also referred
to as &quot;vertices and edges&quot; (vertices is a plural of &quot;vertex&quot;).&lt;&#x2F;p&gt;
&lt;p&gt;Graphs are a really good structure to express &quot;things&quot; and &quot;relationships between things&quot;. If this
sounds general, it&#x27;s because it is! A lot problems can be expressed in terms of graphs, which is why
it&#x27;s such a useful structure to be comfortable with!&lt;&#x2F;p&gt;
&lt;p&gt;Some types of graphs not only store data on the nodes, but on the edges too. But if you ever
happen to read up on &quot;graph databases&quot; you might see words such as &quot;triples&quot; and &quot;quads&quot; come by.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;triples&quot; means there&#x27;s 1 slot to store data per relationship, and &quot;quads&quot; means there&#x27;s two slots
to store data per relationship (e.g. a distinction between &lt;code&gt;A -&amp;gt; B&lt;&#x2F;code&gt; and &lt;code&gt;A &amp;lt;- B&lt;&#x2F;code&gt;). But none of that
matters for this post.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cycles&quot;&gt;Cycles&lt;&#x2F;h3&gt;
&lt;p&gt;If you&#x27;ve read about graphs, you might&#x27;ve seen the words &quot;acyclic&quot;, &quot;cyclic&quot; or &quot;cycles&quot; come by.
This refers to whether or not a graph structure&#x27;s relationships can be followed to create loops.&lt;&#x2F;p&gt;
&lt;p&gt;For example a relationships of &lt;code&gt;A -&amp;gt; B -&amp;gt; A&lt;&#x2F;code&gt; is cyclic. And so is &lt;code&gt;A -&amp;gt; B -&amp;gt; C -&amp;gt; A&lt;&#x2F;code&gt;. Even if loops
don&#x27;t naturally occur in a structure, it can still be &quot;cyclic&quot; if there&#x27;s the possibility of them
occurring in the future. If the structure guarantees no loops can ever occur, it&#x27;s referred to as
&quot;acyclic&quot; (non-cyclic).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;directed-graphs&quot;&gt;directed graphs&lt;&#x2F;h2&gt;
&lt;img src=&quot;&#x2F;assets&#x2F;graphs&#x2F;cyclic_graph.jpg&quot; alt=&quot;cyclic graph&quot; style=&quot;max-width:300px&quot;&gt;
&lt;h3 id=&quot;properties&quot;&gt;Properties&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Property&lt;&#x2F;th&gt;&lt;th&gt;Value&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Cycles&lt;&#x2F;td&gt;&lt;td&gt;Possible&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Max children per node&lt;&#x2F;td&gt;&lt;td&gt;Unconstrained&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Max parents per node&lt;&#x2F;td&gt;&lt;td&gt;Unconstrained&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;about&quot;&gt;About&lt;&#x2F;h3&gt;
&lt;p&gt;The most basic of types is the (cyclic) graph. This type of graph has the fewest constraints, and is
what people usually refer to when they talk about &quot;graphs&quot;. Every node can have an &lt;code&gt;m:n&lt;&#x2F;code&gt;
relationship, and nodes can sometimes even link to themselves directly.&lt;&#x2F;p&gt;
&lt;p&gt;In this kind of generic graph, any connection is allowed. This can make it hard to keep track of, as
when any new connection is added, all assumptions about the graph might have changed, which means
that to draw make any meaningful statements about it, the whole graph needs to be re-evaluated.&lt;&#x2F;p&gt;
&lt;p&gt;These types of graphs are the most flexible, but also provide the fewest guarantees.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;examples&quot;&gt;Examples&lt;&#x2F;h3&gt;
&lt;p&gt;Probably the most common example here is that of a social network. Any person can have a
relationship with any other people, and there&#x27;s no constraint on who they are, and how many
relationships there can be.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;acyclic-graphs&quot;&gt;acyclic graphs&lt;&#x2F;h2&gt;
&lt;img src=&quot;&#x2F;assets&#x2F;graphs&#x2F;acyclic_graph.jpg&quot; alt=&quot;acyclic graph&quot; style=&quot;max-width:300px&quot;&gt;
&lt;h3 id=&quot;properties-1&quot;&gt;Properties&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Property&lt;&#x2F;th&gt;&lt;th&gt;Value&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Can have cycles&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Max children per node&lt;&#x2F;td&gt;&lt;td&gt;Unconstrained&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Max parents per node&lt;&#x2F;td&gt;&lt;td&gt;Unconstrained&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;about-1&quot;&gt;About&lt;&#x2F;h3&gt;
&lt;p&gt;An acyclic graph is similar to a regular graph, but unlike a regular graph it can&#x27;t contain
&lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;graphs&#x2F;#cycles&quot;&gt;cycles&lt;&#x2F;a&gt;. This is useful when using computers to guarantee no infinite loops can occur. For
example when building message-based systems, having a guarantee that no infinite loops can occur can
help with inter-system reliability.&lt;&#x2F;p&gt;
&lt;p&gt;The way acyclic graphs are defined is usually by establishing a hierarchy of &quot;parent nodes&quot; and
&quot;child nodes&quot;. In the image above &lt;code&gt;[B, C, D]&lt;&#x2F;code&gt; are children of &lt;code&gt;A&lt;&#x2F;code&gt;, and &lt;code&gt;A&lt;&#x2F;code&gt; is the parent of &lt;code&gt;[B, C, D]&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The way cycles are prevents is by &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Directed_acyclic_graph&quot;&gt;roughly&lt;&#x2F;a&gt;
applying the following rules to the graph:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;any node can have multiple parent nodes&lt;&#x2F;li&gt;
&lt;li&gt;any node can have multiple child nodes&lt;&#x2F;li&gt;
&lt;li&gt;a parent or sibling node can&#x27;t also be a child node&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is a simplification of the full set of rules, but the general idea should translate. But
acyclic graphs already provide a lot more guarantees than general graphs!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;examples-1&quot;&gt;Examples&lt;&#x2F;h3&gt;
&lt;p&gt;A common example you&#x27;ll encounter is that of software dependencies. Any dependency can have any
other dependencies, but if there&#x27;s cycles in the dependency graph it can&#x27;t resolve (e.g. you can&#x27;t
dependency of yourself).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;trees&quot;&gt;Trees&lt;&#x2F;h2&gt;
&lt;img src=&quot;&#x2F;assets&#x2F;graphs&#x2F;tree.jpg&quot; alt=&quot;tree&quot; style=&quot;max-width:300px&quot;&gt;
&lt;h3 id=&quot;properties-2&quot;&gt;Properties&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Property&lt;&#x2F;th&gt;&lt;th&gt;Value&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Can have cycles&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Max children per node&lt;&#x2F;td&gt;&lt;td&gt;Unconstrained&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Max parents per node&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;about-2&quot;&gt;About&lt;&#x2F;h3&gt;
&lt;p&gt;Trees are a simplification of acyclic graph. They impose an additional constraint that each node
must have exactly one parent (except for the root node, which has none).&lt;&#x2F;p&gt;
&lt;p&gt;A well-known subtype of trees is that of &quot;binary trees&quot; where each node may have up to 2 children.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;examples-2&quot;&gt;Examples&lt;&#x2F;h3&gt;
&lt;p&gt;Rust&#x27;s data model is an example of a tree. Any piece of data must have exactly one parent, but can
share references to multiple child functions. The child functions can&#x27;t outlive the lifetime of the
parent, essentially creating a tree. This is as opposed to for example C, where what you &lt;em&gt;want&lt;&#x2F;em&gt; is
for the memory to be expressed as a tree, but the language &lt;em&gt;allows&lt;&#x2F;em&gt; you to express it as a directed
graph.&lt;&#x2F;p&gt;
&lt;p&gt;Similarly function execution forms a tree, where any function can call multiple functions, but no
single function call ever originates from two callers at the same time, always creating a tree. The
&lt;a href=&quot;http:&#x2F;&#x2F;libdill.org&#x2F;structured-concurrency.html&quot;&gt;topic of structured concurrency&lt;&#x2F;a&gt; covers this well.
The Tl;Dr being: if you can express concurrency as a tree, it&#x27;s a lot easier to reason about. And
the same applies to error handling too. Oh, and HTML.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;logs&quot;&gt;Logs&lt;&#x2F;h2&gt;
&lt;img src=&quot;&#x2F;assets&#x2F;graphs&#x2F;list.jpg&quot; alt=&quot;tree&quot; style=&quot;max-width:300px&quot;&gt;
&lt;h3 id=&quot;properties-3&quot;&gt;Properties&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Property&lt;&#x2F;th&gt;&lt;th&gt;Value&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Can have cycles&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Max children per node&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Max parents per node&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;about-3&quot;&gt;About&lt;&#x2F;h3&gt;
&lt;p&gt;Logs (or lists) are probably the simplest kind of graph out there. Every node has one parent, and at
most one child (except for the root node). One of the most interesting properties they have is that
they provide absolute ordering of the items in them, meaning there&#x27;s never a question which entry
came before which other entry.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;examples-3&quot;&gt;Examples&lt;&#x2F;h3&gt;
&lt;p&gt;Logs are widely applicable. The most common use is probably as &quot;arrays&quot; in programming language, or
sequences of bytes in memory. But for databases lists are fantastic as a model to track events in
that can be processed and replayed into more types that can be queried.&lt;&#x2F;p&gt;
&lt;p&gt;Logs are generally used for anything involving time too. For example in accounting data is tracked
as a series of events where money goes in, and money goes out. And anything commonly referred to as
a &quot;feed&quot; also tracks data over time.&lt;&#x2F;p&gt;
&lt;p&gt;Logs are everywhere, and despite their relatively simple nature, a lot of problems can be expressed
as a log.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In this post we&#x27;ve talked about different types of graphs, their properties, and examples of them.
This an example of the idea of &quot;more constraints can be better&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Something I haven&#x27;t mentioned is how well some graph types map to data visualizations. In particular
trees can be visualized nicely as either a &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Tools&#x2F;Performance&#x2F;Flame_Chart&quot;&gt;flame
chart&lt;&#x2F;a&gt;, &lt;a href=&quot;http:&#x2F;&#x2F;www.brendangregg.com&#x2F;flamegraphs.html&quot;&gt;flame
graph&lt;&#x2F;a&gt;, or &lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;netflix-techblog&#x2F;netflix-flamescope-a57ca19d47bb&quot;&gt;flame
scope&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks for reading!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;thanks&quot;&gt;Thanks&lt;&#x2F;h2&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;_lrlna&quot;&gt;@_lrlna&lt;&#x2F;a&gt; for helping create the illustrations, and helping
bounce ideas off of!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Runtime</title>
            <pubDate>Tue, 16 Apr 2019 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/runtime/</link>
            <guid>https://blog.yoshuawuyts.com/runtime/</guid>
            <description>&lt;p&gt;Asynchronous programming in Rust continues to make exciting strides, including the upcoming
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;59725&quot;&gt;stabilization of the futures API&lt;&#x2F;a&gt;. But, while these core APIs make it &lt;em&gt;possible&lt;&#x2F;em&gt; to write async
Rust code today, it&#x27;s not easy: it&#x27;s a far cry from the smoothness of synchronous code.&lt;&#x2F;p&gt;
&lt;p&gt;The vision of the Async Ecosystem WG is to refine the async Rust experience until it matches the
quality and ease of working with today&#x27;s &lt;code&gt;std&lt;&#x2F;code&gt;. There are a lot of components in that vision,
including async&#x2F;await syntax and borrow checker integration. Today, though, we&#x27;d like to introduce
another component: &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustasync&#x2F;runtime&quot;&gt;Runtime&lt;&#x2F;a&gt;, a crate that makes working with async code feel closer to working with
&lt;code&gt;std&lt;&#x2F;code&gt;, and a stepping stone toward ecosystem standardization.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;our-north-star&quot;&gt;Our north star&lt;&#x2F;h2&gt;
&lt;p&gt;The goal of the Runtime crate is to smooth out the experience of setting up an asynchronous
application. It does this by:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Removing headaches for setting up a shared async runtime, including both I&#x2F;O and async executors.&lt;&#x2F;li&gt;
&lt;li&gt;Carefully hewing to Rust API conventions (following &lt;code&gt;std&lt;&#x2F;code&gt;&#x27;s lead).&lt;&#x2F;li&gt;
&lt;li&gt;Standardizing a runtime interface to decouple applications from underlying backing implementations -- and allowing easy customization through creating your own runtime implementation.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We would love to see a future in which async Rust is part of &lt;code&gt;std&lt;&#x2F;code&gt;, has ubiquitous platform support,
and the backing implementations can be swapped out the same way allocators can be swapped today. We ultimately
imagine writing a TCP echo server, using potential syntax like &lt;code&gt;await?&lt;&#x2F;code&gt; and &lt;code&gt;for await&lt;&#x2F;code&gt;, with code like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::futures::net::TcpListener;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; std::io::Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; listener = TcpListener::bind(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Listening on &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;local_addr&lt;&#x2F;span&gt;&lt;span&gt;()?);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    #[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(parallel)]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; await? stream in listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;incoming&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Accepting from: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, stream.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;peer_addr&lt;&#x2F;span&gt;&lt;span&gt;()?);
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(reader, writer) = &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; stream.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        await? reader.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;copy_into&lt;&#x2F;span&gt;&lt;span&gt;(writer);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This example is 13 lines, but sets up a cross-platform runtime consisting of an executor, reactor,
and threadpool. It then creates a TCP listener on port 8080 that handles incoming connections in
parallel on all cores, and asynchronously streams all incoming bytes back out to the sender. That&#x27;s
a lot!&lt;&#x2F;p&gt;
&lt;p&gt;In typical Rust fashion, we want to make it so choosing between performance and ergonomics doesn&#x27;t
have to be a choice you ever have to make. And we also want to provide a high degree of flexibility
by not coupling these APIs to any particular async runtime, but rather letting you easily swap them
out.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;runtime-today&quot;&gt;Runtime today&lt;&#x2F;h2&gt;
&lt;p&gt;While the example above isn&#x27;t quite possible today, we&#x27;re not far from getting there either. Runtime provides
most of what you&#x27;re seeing there, modulo some language features:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;feature&lt;&#x2F;span&gt;&lt;span&gt;(async_await, await_macro, futures_api)]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;futures::prelude::*;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;runtime::net::TcpListener;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;runtime&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; std::io::Result&amp;lt;()&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; listener = TcpListener::bind(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:8080&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Listening on &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;local_addr&lt;&#x2F;span&gt;&lt;span&gt;()?);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; incoming = listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;incoming&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span&gt;Some(stream) = await!(incoming.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;()) {
&lt;&#x2F;span&gt;&lt;span&gt;        runtime::spawn(async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; stream = stream?;
&lt;&#x2F;span&gt;&lt;span&gt;            println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Accepting from: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, stream.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;peer_addr&lt;&#x2F;span&gt;&lt;span&gt;()?);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(reader, writer) = &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; stream.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;            await!(reader.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;copy_into&lt;&#x2F;span&gt;&lt;span&gt;(writer))?;
&lt;&#x2F;span&gt;&lt;span&gt;            Ok::&amp;lt;(), std::io::Error&amp;gt;(())
&lt;&#x2F;span&gt;&lt;span&gt;        });
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;attributes&quot;&gt;Attributes&lt;&#x2F;h3&gt;
&lt;p&gt;Runtime introduces 3 attributes to enable the use of await anywhere, and swap between different
runtimes. Each Runtime is bound locally to the initializing thread. This enables the testing of
different runtimes during testing or benchmarking.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;runtime&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;runtime&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;test&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;my_test&lt;&#x2F;span&gt;&lt;span&gt;() {}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;runtime&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;bench&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;my_bench&lt;&#x2F;span&gt;&lt;span&gt;() {}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;runtimes&quot;&gt;Runtimes&lt;&#x2F;h3&gt;
&lt;p&gt;Switching runtimes is a one-line change:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Use the default Native Runtime
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;runtime&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F;&#x2F; Use the Tokio Runtime
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;runtime&lt;&#x2F;span&gt;&lt;span&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;(runtime_tokio::Tokio)]
&lt;&#x2F;span&gt;&lt;span&gt;async &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The following backing runtimes are available today:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;runtime-native&quot;&gt;Runtime Native (default)&lt;&#x2F;a&gt; provides a thread pool, bindings to the
OS, and a concurrent scheduler.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;runtime-tokio&quot;&gt;Runtime Tokio&lt;&#x2F;a&gt; binds to Tokio&#x27;s runtime, which provides a thread
pool, bindings to the OS, and a work-stealing scheduler.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We hope to eventually be able to provide Runtimes for &lt;em&gt;all&lt;&#x2F;em&gt; platforms (Fuschia, WASM, Android,
Redox, et al.) and enable experimentation on building the underlying bindings. Hardware, operating
systems, and research continuously improve.&lt;&#x2F;p&gt;
&lt;p&gt;Runtime provides a foundation for Async Rust that anticipates change, and allows us embrace progress
and stability without needing to compromise.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;bindings&quot;&gt;Bindings&lt;&#x2F;h3&gt;
&lt;p&gt;Currently Runtime comes with async bindings to &lt;code&gt;net::tcp&lt;&#x2F;code&gt; and &lt;code&gt;net::udp&lt;&#x2F;code&gt;. We expect to add
&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Unix_domain_socket&quot;&gt;UDS&lt;&#x2F;a&gt; and Timer support in the near future.&lt;&#x2F;p&gt;
&lt;p&gt;Async fs bindings are probably a bit further out because currently we don&#x27;t know of any runtimes
that provide a coherent story, and there are still some core traits missing from Futures to round
out the ergonomics.&lt;&#x2F;p&gt;
&lt;p&gt;But all in all we think this provides a great foundation to start working on asynchronous networked
applications that don&#x27;t want to lock themselves into a single runtime.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;ve introduced Runtime, a platform-agnostic library that intends to make Async Rust both flexible
and easy. It provides network bindings to multiple runtimes today, and provides a stable foundation
for writing networked applications that don&#x27;t want to be bound to a single vendor.&lt;&#x2F;p&gt;
&lt;p&gt;Runtime is available on GitHub as &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustasync&#x2F;runtime&quot;&gt;rustasync&#x2F;runtime&lt;&#x2F;a&gt;, and
on crates.io as &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;runtime&quot;&gt;runtime&lt;&#x2F;a&gt;. Happy hacking!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>contexts</title>
            <pubDate>Sun, 31 Mar 2019 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/contexts/</link>
            <guid>https://blog.yoshuawuyts.com/contexts/</guid>
            <description>&lt;p&gt;I&#x27;ve recently been thinking a lot about Rust&#x27;s ergonomics, especially around async and error
handling. I&#x27;ve come up with quite a few fun ideas that I&#x27;m excited to share. But I think that before
I can meaningfully explain their significance, it&#x27;s important to take a step back and create a lens
through which to view them.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Note: I&#x27;m don&#x27;t consider myself a language designer, so don&#x27;t take this as language design advise.
I mostly just wanted to talk about how I&#x27;m currently thinking about things, and figured writing this
in long-form might be better than as a string of tweets. Anyway, this is all just my opinion &amp;amp;
thoughts, and I&#x27;m not on Rust&#x27;s lang team so this is in no way representative of anyone on there.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;And with that said, let&#x27;s dig in!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;matrix&quot;&gt;Matrix&lt;&#x2F;h2&gt;
&lt;p&gt;I think one of the cool things about Rust is that it&#x27;s a single language that allows you to write
the low-level bits of a program, and the high-level abstractions in the same language. This means
that we have a language that needs to balance an incredible amount of different aspects, and merge
them into a cohesive whole.&lt;&#x2F;p&gt;
&lt;p&gt;This is not easy, and I can&#x27;t claim to have nailed the grand unifying theory of language design. But
I do think I have a neat angle to apply to &lt;em&gt;high level Rust design&lt;&#x2F;em&gt;. It&#x27;s the following table:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Synchronous&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Asynchronous&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Infallible&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn foo () {}&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn foo() -&amp;gt; Future&amp;lt;Item = ()&amp;gt;{}&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Fallible&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn foo () -&amp;gt; Result&amp;lt;(), io::Error&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn foo() -&amp;gt; Future&amp;lt;Item = Result&amp;lt;(), io::Error&amp;gt;&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;I think for high-level Rust there are essentially 2 axis, and 4 different language combinations.
There&#x27;s the question whether operations can fail or not. And the question whether functions can be
suspended or not (e.g. futures in this case, though generators behave similarly).&lt;&#x2F;p&gt;
&lt;p&gt;Using this lens we can explain some of the historical problems we&#x27;ve had. E.g. the original Futures
design didn&#x27;t care to handle the Infallible + Asynchronous case; probably because it didn&#x27;t consider
anyone might ever need it. But then Fuschia came along, and very clearly &lt;em&gt;did&lt;&#x2F;em&gt; need it, which meant
another round of design was needed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;contexts&quot;&gt;Contexts&lt;&#x2F;h2&gt;
&lt;p&gt;In fact, a good way of viewing the different axis in the table is as &lt;em&gt;contexts&lt;&#x2F;em&gt;. If we&#x27;re in a
function that returns a &lt;code&gt;Result&lt;&#x2F;code&gt;, we&#x27;re in a &lt;em&gt;fallible context&lt;&#x2F;em&gt;. If we&#x27;re in a function that returns
a &lt;code&gt;Future&lt;&#x2F;code&gt;, we&#x27;re in an &lt;em&gt;async context&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Rust&#x27;s language design acknowledges that async contexts are a real thing, and has appropriately
introduced the &lt;code&gt;async fn&lt;&#x2F;code&gt; keyword. This sugar has allowed the language to remove a lot of
boilerplate around suspension points, and borrowing across them, creating a better experience
throughout.&lt;&#x2F;p&gt;
&lt;p&gt;I think we have similar boilerplate problems with &lt;code&gt;Result&lt;&#x2F;code&gt;, and by treating it as the dual of &lt;code&gt;async fn&lt;&#x2F;code&gt; we could create a better experience -- in particular for fallible contexts that don&#x27;t return
values (getting rid of &lt;code&gt;Ok(())&lt;&#x2F;code&gt; &lt;em&gt;everywhere&lt;&#x2F;em&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;Given we could have a &lt;code&gt;throw&lt;&#x2F;code&gt; keyword in argument position, we could then have clearer signaling of
the context we&#x27;re executing in, and in turn remove all the boilerplate currently required to achieve
the same result.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Synchronous&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Asynchronous&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Infallible&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn foo () {}&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;async fn foo() {}&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Fallible&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;fn foo () -&amp;gt; throw io::Error&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;async fn foo() -&amp;gt; throw io::Error&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Just to finish the thought: fallible contexts would pair with a &lt;code&gt;throw&lt;&#x2F;code&gt; keyword in body position to
return errors:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; current
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;Err(e);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; new
&lt;&#x2F;span&gt;&lt;span&gt;throw e;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Also none of this is my idea. I believe various stages of RFCs and discussions exist around this in
the wild. But I hope the general point makes sense about contexts.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;applications-of-the-context-lens&quot;&gt;Applications of the Context Lens&lt;&#x2F;h2&gt;
&lt;p&gt;Some other language features I&#x27;ve been applying this lens to is extensions of async await. For
example yielding a &lt;code&gt;TcpStream&lt;&#x2F;code&gt; is always fallible, so what if we introduced a way to consider
&lt;em&gt;fallible iterators&lt;&#x2F;em&gt;? What about &lt;em&gt;async fallible iterators&lt;&#x2F;em&gt;?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; synchonous, current
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; listener = TcpListener::bind(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;127.0.0.1:80&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; stream in listener.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;incoming&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; stream = stream?;
&lt;&#x2F;span&gt;&lt;span&gt;    stream.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write_all&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;hello world&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I think most people would agree that &lt;code&gt;let stream = stream?&lt;&#x2F;code&gt; feels like a bit of boilerplate that
could probably be considered in the language design. What would it look like if we could fill out
this chart?&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Synchronous&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Asynchronous&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Infallible&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;for item in iterator {}&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;?&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Fallible&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;?&lt;&#x2F;td&gt;&lt;td&gt;?&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Similarly there&#x27;s been talk about adding a &lt;code&gt;select {}&lt;&#x2F;code&gt; keyword for futures. There&#x27;s currently a
&lt;code&gt;select!{}&lt;&#x2F;code&gt; and &lt;code&gt;try_select!{}&lt;&#x2F;code&gt; macro in the &lt;code&gt;future-preview&lt;&#x2F;code&gt; crate.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The first future to complete will assign its value to `res`.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; All other futures are then cancelled.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; res = await select {
&lt;&#x2F;span&gt;&lt;span&gt;    my_struct.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;do_thing&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;    other_struct.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;thing&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The synchronous counterpart to awaiting futures would probably blocking threads until a thread&#x27;s
&lt;code&gt;JoinHandle&lt;&#x2F;code&gt; returns. Filling out the chart again, what would each entry be?&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Synchronous&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;th&gt;&lt;strong&gt;Asynchronous&lt;&#x2F;strong&gt;&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Infallible&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;?&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;await select {}&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Fallible&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;?&lt;&#x2F;td&gt;&lt;td&gt;?&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;other-contexts&quot;&gt;Other Contexts&lt;&#x2F;h2&gt;
&lt;p&gt;But the above is not the only way to slice our cake. There are many more constraints to consider
when thinking about features:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Do we have &lt;code&gt;std&lt;&#x2F;code&gt; support?&lt;&#x2F;li&gt;
&lt;li&gt;Are we in a &lt;code&gt;const&lt;&#x2F;code&gt; context?&lt;&#x2F;li&gt;
&lt;li&gt;Are we in a browser? E.g. &lt;code&gt;wasm32-unknown-unknown&lt;&#x2F;code&gt; probably means we can&#x27;t use the usual
networking &#x2F; filesystem APIs.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And the slightly more difficult topic of:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;How does it compare if we tried to solve this problem in userland?&lt;&#x2F;li&gt;
&lt;li&gt;How does this feature interact with future follow-ups?&lt;&#x2F;li&gt;
&lt;li&gt;How does this feature interact with currently proposed language extensions?&lt;&#x2F;li&gt;
&lt;li&gt;Who are we building this feature for?&lt;&#x2F;li&gt;
&lt;li&gt;Are there any unsolved problem&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;And that&#x27;s it. There&#x27;s not much of a conclusion here. But I wanted to write down how I&#x27;m currently
thinking about (language) design, and the lens I&#x27;m applying. I think building up lenses like these
are useful to consider design decisions through, and I hope I can build up a bigger collection of
these as time goes on.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, I hope this is useful!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>DSLs II: Challenges</title>
            <pubDate>Sun, 03 Mar 2019 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/dsls-2/</link>
            <guid>https://blog.yoshuawuyts.com/dsls-2/</guid>
            <description>&lt;p&gt;&lt;em&gt;This post is part of a series:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;dsls-1&quot;&gt;&lt;em&gt;DSLs I: Introduction&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;DSLs II: Challenges (current)&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;In the last post we examined some examples of DSLs in Rust, and established that
using DSLs in Rust is not uncommon.&lt;&#x2F;p&gt;
&lt;p&gt;In this post we&#x27;ll look at some of the challenges there exist around DSLs in Rust, examine example
from the ecosystem, and look at alternatives we can draw inspiration from.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Note: While I might be drawing on challenges from existing technologies, I would like to take a
moment to emphasize that I have the utmost respect and admiration for these technologies, and the
people that have created them. They continue to play a crucial role in pushing the boundaries of
what&#x27;s possible, and without them we couldn&#x27;t be having this conversation. This piece exists solely
to enumerate trends, and look towards the future of potential ways we can improve the state of DSLs
in Rust.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;compile-time-compilation&quot;&gt;Compile-time Compilation&lt;&#x2F;h2&gt;
&lt;p&gt;When building &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;choojs&#x2F;nanohtml&quot;&gt;nanohtml&lt;&#x2F;a&gt; we found that we needed to target
Node.js and browsers differently. For browsers we wanted to create real DOM nodes to perform DOM
diffing, but when targeting Node.js all we needed was to concatenate strings.&lt;&#x2F;p&gt;
&lt;p&gt;In addition we wanted to cut down on the code size and startup time in the browser. So instead of
shipping an HTML parsers &#x2F; interpreter in the final output, we decided to perform the optimization
step ahead of time, and just ship the necessary glue code + resulting code.&lt;&#x2F;p&gt;
&lt;p&gt;We found this ended up cutting down our resulting output size by about 90% for smaller programs, and
reduced our startup time by about 4x. Not to speak of improved runtime performance and user
experience by not having to worry about continuously needing to re-compile the code when switching
between views, making performance less of a concern throughout.&lt;&#x2F;p&gt;
&lt;p&gt;However a downside of doing this in JavaScript was that it was never really built to be compiled.
Every compilation step required significant work to harden and optimize, and even then the resulting
output wasn&#x27;t even close to Rust&#x27;s compiler output. By comparison Rust&#x27;s macro system is like day
and night.&lt;&#x2F;p&gt;
&lt;p&gt;The story of &lt;code&gt;nanohtml&lt;&#x2F;code&gt; is only an example. In practice these techniques have been applied this to
other areas too (CSS, assets, GLSL), and found comparable improvements. The takeaway here for DSLs
in Rust would be:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;During compilation DSLs should have the option to be compiled for target platforms.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;interpolation&quot;&gt;Interpolation&lt;&#x2F;h2&gt;
&lt;p&gt;The use of having DSLs reside inside program source, rather than in separate files, is so it&#x27;s
possible to directly plug variables into the DSL. For example if we wanted to create a list of
fishes from a variable, we could quickly use an inline &lt;code&gt;map&lt;&#x2F;code&gt; statement:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;html &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;require&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;nanohtml&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fishes &lt;&#x2F;span&gt;&lt;span&gt;= [&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;bass&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;, &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;carp&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;, &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;trout&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;doc &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;html&lt;&#x2F;span&gt;&lt;span&gt;`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;  &amp;lt;ul&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;    ${&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fishes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fish &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;html&lt;&#x2F;span&gt;&lt;span&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&amp;lt;li&amp;gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fish&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;}&amp;lt;&#x2F;li&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;)}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;  &amp;lt;&#x2F;ul&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;`
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Compare that to, say, handlebars syntax in Rust:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;fishes.hbs&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;html&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-html &quot;&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ul&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;  {% for fish in fishes %}
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;li&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;{{fish}}&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;li&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;  {% endfor %}
&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;ul&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;fishes.rs&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; fishes: Vec&amp;lt;String&amp;gt; = [&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;bass&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;carp&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;trout&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; vals = json!({&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;fishes&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;: fishes});
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; doc = reg.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;render_template&lt;&#x2F;span&gt;&lt;span&gt;(includ_str!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;fishes.hbs&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;), vals);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The handlebars version is spread out over multiple files, defines new operators for control flow,
and has a fair bit of indirection in what&#x27;s going on. Also in the Rust version, the &lt;code&gt;json!()&lt;&#x2F;code&gt; macro
defines a second mode of variable interpolation which is different from the HTML interpolation.&lt;&#x2F;p&gt;
&lt;p&gt;These different syntaxes for interpolation can make learning how to use a particular DSL a bit
tricky. Some of Rust&#x27;s DSLs use &lt;code&gt;#var_name&lt;&#x2F;code&gt;, others use &lt;code&gt;{var}&lt;&#x2F;code&gt;, yet again others seem to just pick
up on the environment&#x27;s variables and interpolate them if they overlap (which is kind of what the
&lt;code&gt;json!()&lt;&#x2F;code&gt; macro seems to do.)&lt;&#x2F;p&gt;
&lt;p&gt;The takeaway here would be:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;DSLs benefit from being able to interpolate variables, and from consistency in interpolation
syntax.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;escaping&quot;&gt;Escaping&lt;&#x2F;h2&gt;
&lt;p&gt;A big constraint Rust&#x27;s DSLs currently have is that they use &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;proc_macro&#x2F;index.html&quot;&gt;proc
macros&lt;&#x2F;a&gt;, and inherit the limitations that proc
macros impose. Most notably the fact that every token inside the macro needs to be valid Rust. Which
includes the requirement that for example braces need to match up, strings closed, and more. E.g.
any DSL made in this way essentially can only exist in the subset of valid Rust tokens.&lt;&#x2F;p&gt;
&lt;p&gt;This limitation might be fine for some simpler DSLs. But when trying to inline other languages
directly, this can be problematic. For example this problem has been evident in &lt;code&gt;typed-html&lt;&#x2F;code&gt;, where
not all of HTML can be expressed, and workarounds in the syntax have been implemented. This is
not ideal because it means that we&#x27;re introducing a library-specific learning curve even for people
that already fluent in HTML. In essence we&#x27;re no longer implementing our target DSL, but a
&lt;em&gt;dialect&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;typed_html::{html, dom::DOMTree};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; The inline text here has to be quoted or else compilation fails.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; doc: DOMTree&amp;lt;String&amp;gt; = html!{
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;lt;p&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Hello world&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;lt;&#x2F;p&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; doc_str = doc.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are varying degrees of workarounds that can be employed here, but the takeaway is:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Relying on Rust token streams as the base building block for the DSL means not all DSLs can be
expressed.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;tooling&quot;&gt;Tooling&lt;&#x2F;h2&gt;
&lt;p&gt;Something that feels quite undervalued for DSLs is the ability to integrate with tooling. A clear
example of this in Rust is the doc comments DSL, which editors can syntax highlight, and formatters
can auto-format (or so I hope they will be, in the future).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;dsls-2&#x2F;.&#x2F;screenshot.png&quot; alt=&quot;syntax highlighting for Rust doc comments in vim&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Doc comments in Rust are special because they&#x27;re built directly into the language.
But in JavaScript there are quite a few DSLs that have tooling integration through the use of the
language-standard &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;JavaScript&#x2F;Reference&#x2F;Template_literals#Tagged_templates&quot;&gt;tagged template
literals&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;These act as a clear DSL-bound for the language, where it usually starts with a declaration of which
DSL is about to follow, and continues with the DSL body. We&#x27;ve seen it before in the HTML
example. But it works for other DSLs too!&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; CSS
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;style &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;css&lt;&#x2F;span&gt;&lt;span&gt;`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;  .button { color: black }
&lt;&#x2F;span&gt;&lt;span&gt;`
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; SQL
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table &lt;&#x2F;span&gt;&lt;span&gt;= &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;piano&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;query &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;sql&lt;&#x2F;span&gt;&lt;span&gt;`
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;    DROP TABLE ${&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;`
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A great example of an editor plugin that works well with DSLs is Atom&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gandm&#x2F;language-babel#javascript-tagged-template-literal-grammar-extensions&quot;&gt;language-babel
package&lt;&#x2F;a&gt;.
Some of the features it supports include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Syntax highlighting for CSS, HTML template tags.&lt;&#x2F;li&gt;
&lt;li&gt;CSS autocompletion.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.emmet.io&#x2F;&quot;&gt;Emmet html expansion&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;HTML tags autocompletion (sadly on for JSX, not template strings)&lt;&#x2F;li&gt;
&lt;li&gt;ability to add syntax highlighting support for other languages too&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Imagine if we could do all these things in Rust! What if we could take things even further: with
integrations and support for many more languages, engines and tools. Or at the very least: imagine a
future where it&#x27;d be possible to visually tell when a value is interpolated in Rust DSLs. To
summarize:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Having a consistent way of delimiting DSLs in Rust would allow for better integration with
tooling.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;So far we&#x27;ve talked about some of the challenges that DSLs have in Rust. This is by no means a
comprehensive list, but it should give you an idea of some of the ecosystem-wide challenges we face.&lt;&#x2F;p&gt;
&lt;p&gt;To recap the challenges:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;During compilation DSLs should have the option to be compiled for target platforms.&lt;&#x2F;li&gt;
&lt;li&gt;DSLs benefit from being able to interpolate variables, and from consistency in interpolation
syntax.&lt;&#x2F;li&gt;
&lt;li&gt;Relying on Rust token streams as the base building block for the DSL means not all DSLs can be
expressed.&lt;&#x2F;li&gt;
&lt;li&gt;Having a consistent way of delimiting DSLs in Rust would allow for better integration with tooling.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And that&#x27;s where I want to leave this post. In a future post we&#x27;ll talk about ways of solving these
challenges for Rust as a whole, and outline possible steps we can take to get there.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;New episode coming soon.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>async ecosystem wg</title>
            <pubDate>Wed, 27 Feb 2019 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/async-ecosystem-wg/</link>
            <guid>https://blog.yoshuawuyts.com/async-ecosystem-wg/</guid>
            <description>&lt;p&gt;12 months ago, the first iteration of the networking working group kicked off. 6
months later we underwent change, and created 3 sub-working groups. It&#x27;s a new
year, a new rust edition, and a good time to re-evaluate our organizational
structures.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-path-taken&quot;&gt;THE PATH TAKEN&lt;&#x2F;h2&gt;
&lt;p&gt;During the last set of organizational changes we came up with with a structure
of 3 sub-working groups:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;web networking:&lt;&#x2F;strong&gt; focused on improving the experience of building web
services in rust.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;async networking:&lt;&#x2F;strong&gt; focused on creating language &amp;amp; ecosystem support for
async primitives such as
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;futures-preview&#x2F;0.3.0-alpha.13&#x2F;futures&#x2F;&quot;&gt;Futures&lt;&#x2F;a&gt; and
&lt;code&gt;async&#x2F;await&lt;&#x2F;code&gt; syntax.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;embedded networking:&lt;&#x2F;strong&gt; focused on creating abstractions for async support on
&lt;code&gt;#[no_std]&lt;&#x2F;code&gt; platforms.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This worked well for a while, but it quickly became clear that this structure
came with non-trivial overhead.&lt;&#x2F;p&gt;
&lt;p&gt;Organizing meetings for the working groups, between
working groups, and with the core team took effort. Enough effort that between
deadlines, holidays and other events, involvement wasn&#x27;t consistent.&lt;&#x2F;p&gt;
&lt;p&gt;Another challenge has been to create clear communication to people outside of
the working groups. Between 3 sub working groups, libraries in different
organizations, and multiple channels it can be hard to keep up with what&#x27;s going
on.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-path-ahead&quot;&gt;THE PATH AHEAD&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;ll be changing our current structure to a new structure of 2 separate working
groups:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;async foundations:&lt;&#x2F;strong&gt; focused on progressing the async primitives in the
language and compiler.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;async ecosystem:&lt;&#x2F;strong&gt; focused on progressing the ecosystem around the async
foundations.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The async foundations working group will operate &lt;a href=&quot;http:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2019&#x2F;02&#x2F;22&#x2F;rust-lang-team-working-groups&#x2F;&quot;&gt;as part of the lang
WG&lt;&#x2F;a&gt;,
similar to the traits, grammar, and FFI working groups.&lt;&#x2F;p&gt;
&lt;p&gt;The async ecosystem working group will live under
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustasync&quot;&gt;github.com&#x2F;rustasync&lt;&#x2F;a&gt;. Projects we&#x27;ll be working
on include the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tide&#x2F;0.0.5&#x2F;tide&#x2F;&quot;&gt;Tide web framework&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;romio&#x2F;0.3.0-alpha.2&#x2F;romio&#x2F;&quot;&gt;Romio
reactor&lt;&#x2F;a&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;juliex&#x2F;0.3.0-alpha.1&#x2F;juliex&#x2F;&quot;&gt;Juliex
executor&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We believe that by creating these projects we&#x27;ll be able to better identify
which pieces in the ecosystem are missing. And identify where it makes sense to
create shared abstractions.&lt;&#x2F;p&gt;
&lt;p&gt;A historical example can be found in Romio and Juliex. The experience of
writing them has been &lt;a href=&quot;https:&#x2F;&#x2F;boats.gitlab.io&#x2F;blog&#x2F;post&#x2F;wakers-ii&#x2F;&quot;&gt;a key
driver&lt;&#x2F;a&gt; in the decision to
simplify the
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nightly&#x2F;std&#x2F;task&#x2F;struct.Waker.html&quot;&gt;&lt;code&gt;std::task::Waker&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
type, providing a better interface for everyone.&lt;&#x2F;p&gt;
&lt;p&gt;We expect the new working group structure will allow us to create better
results, communicate better, and in the end help elevate Rust&#x27;s async story to
be second to none.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;become-involved&quot;&gt;BECOME INVOLVED&lt;&#x2F;h2&gt;
&lt;p&gt;The async ecosystem working group has text-only meetings every &lt;a href=&quot;https:&#x2F;&#x2F;everytimezone.com&#x2F;s&#x2F;526cb9d1&quot;&gt;Thursdays at 4pm
UTC&lt;&#x2F;a&gt; on &lt;a href=&quot;https:&#x2F;&#x2F;discordapp.com&#x2F;channels&#x2F;442252698964721669&#x2F;474974025454452766&quot;&gt;our Discord
channel&lt;&#x2F;a&gt;.
We have &lt;a href=&quot;https:&#x2F;&#x2F;paper.dropbox.com&#x2F;doc&#x2F;Rust-Web-WG-Meeting--AYW9XbFMYXQNjU_5A0hW6eBLAg-lsZeIpXH6yHQ93zlf4vrM&quot;&gt;agendas for each
meeting&lt;&#x2F;a&gt;,
and store minutes in a public repository so people can catch up async. The
meetings are open to anyone interested, and we encourage people to add questions
&#x2F; topics to the agenda to discuss.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks everyone for reading. We&#x27;re excited for the future of async Rust, and we
hope you are too!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>DSLs I: Introduction</title>
            <pubDate>Sun, 24 Feb 2019 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/dsls-1/</link>
            <guid>https://blog.yoshuawuyts.com/dsls-1/</guid>
            <description>&lt;p&gt;&lt;em&gt;This post is part of a series:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;DSLs I: Introduction (current)&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;dsls-2&quot;&gt;&lt;em&gt;DSLs II: Challenges&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Domain Specific Languages (DSLs) are everywhere. Whether it&#x27;s writing regex
filters, accessing file system paths, of building websites. It&#x27;s likely you&#x27;ll
be using DSLs to complete the task.&lt;&#x2F;p&gt;
&lt;p&gt;In this post I want to talk about different kinds of DSLs in Rust, and some of
the properties they have.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;regular-expressions&quot;&gt;Regular Expressions&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;regex&#x2F;1.1.0&#x2F;regex&#x2F;&quot;&gt;regex crate&lt;&#x2F;a&gt; uses runtime compilation
of DSLs to state machines. This is the example code to find a date:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;regex::Regex;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; re = Regex::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;^\d{4}-\d{2}-\d{2}$&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;assert!(re.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_match&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;2014-01-01&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In their docs they claim that: &quot;compilation can take anywhere from a few
microseconds to a few milliseconds depending on the size of the regex&quot;
(&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;regex&#x2F;1.1.0&#x2F;regex&#x2F;#example-avoid-compiling-the-same-regex-in-a-loop&quot;&gt;src&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;file-paths&quot;&gt;File Paths&lt;&#x2F;h2&gt;
&lt;p&gt;Rust&#x27;s stdlib includes
&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;path&#x2F;index.html&quot;&gt;&lt;code&gt;std::path&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to define file
system lookups. This is an example of how to create a new path:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::path::Path;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Note: this example does work on Windows
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; path = Path::new(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;.&#x2F;foo&#x2F;bar.txt&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Different operating systems use different delimiters to access
files, so Rust normalizes delimiters during compilation to ensure paths are
accessed correctly (&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;path&#x2F;struct.Path.html&quot;&gt;src&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;string-formatting&quot;&gt;String Formatting&lt;&#x2F;h2&gt;
&lt;p&gt;Similar to file paths, Rust&#x27;s stdlib includes mechanisms for &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;fmt&#x2F;index.html&quot;&gt;string
formatting&lt;&#x2F;a&gt;. This is an example of
how to format different inputs to strings:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;format!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Hello&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; =&amp;gt; &amp;quot;Hello&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;format!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Hello, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;world&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; =&amp;gt; &amp;quot;Hello, world!&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;format!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{value}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, value=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;);      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; =&amp;gt; &amp;quot;4&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;format!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{:04}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;42&lt;&#x2F;span&gt;&lt;span&gt;);             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; =&amp;gt; &amp;quot;0042&amp;quot; with leading zeros
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Rust&#x27;s string formatting is quite rich. Values can be repeated, padded, shifted,
delimited and more. But no runtime cost is paid for this as all the logic is
encoded during compilation, making this a zero-overhead abstraction.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;html&quot;&gt;HTML&lt;&#x2F;h2&gt;
&lt;p&gt;HTML is a DSL commonly used for web programming, similar to how CSS or SQL are
used. It&#x27;s not uncommon to find HTML embedded inside application code in a lot
of programming languages. And this increasingly true for Rust too.&lt;&#x2F;p&gt;
&lt;p&gt;A crate that provides a DSL for this is
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;typed-html&#x2F;0.1.1&#x2F;typed_html&#x2F;&quot;&gt;&lt;code&gt;typed-html&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. It provides
type-checked HTML, meaning the compiler checks your HTML syntax just like it
checks your Rust syntax. And &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;bodil&#x2F;status&#x2F;1063929911331696640&quot;&gt;the resulting
error reporting&lt;&#x2F;a&gt;) is
similarly fantastic!&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s an example HTML document written using &lt;code&gt;typed-html&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;#![&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;recursion_limit &lt;&#x2F;span&gt;&lt;span&gt;= &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;128&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;typed_html::{html, for_events};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;typed_html::dom::{DOMTree, VNode};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;typed_html::types::Metadata;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; doc: DOMTree&amp;lt;String&amp;gt; = html!{
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;lt;html&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &amp;lt;head&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &amp;lt;link rel=LinkType::StyleSheet href=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;bundle.css&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&#x2F;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &amp;lt;&#x2F;head&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &amp;lt;body&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &amp;lt;p class=[&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;urgent&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;question&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;]&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;          &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;But how does she eat?&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &amp;lt;&#x2F;p&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;        {
&lt;&#x2F;span&gt;&lt;span&gt;          (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;| {
&lt;&#x2F;span&gt;&lt;span&gt;            html!(&amp;lt;p&amp;gt;{
&lt;&#x2F;span&gt;&lt;span&gt;              text!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;{}. N&amp;#39;est pas une chatte.&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, i)
&lt;&#x2F;span&gt;&lt;span&gt;            }&amp;lt;&#x2F;p&amp;gt;)
&lt;&#x2F;span&gt;&lt;span&gt;          })
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;        &amp;lt;p&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;          &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&amp;lt;img src=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;javascript:alert(&amp;#39;pwned lol&amp;#39;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &amp;lt;&#x2F;p&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &amp;lt;&#x2F;body&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;lt;&#x2F;html&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;  };
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; doc_str = doc.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see in the example above, the syntax is quite similar to HTML, but
isn&#x27;t &lt;em&gt;exactly&lt;&#x2F;em&gt; HTML.&lt;&#x2F;p&gt;
&lt;p&gt;The culprit here is that &lt;code&gt;typed-html&lt;&#x2F;code&gt; uses procedural macros to define the
syntax. Which means the crate is bound by the limitation that everything inside
a macro must be valid Rust tokens. For example that means that all braces must
come in pairs. No invalid tokens can be used. And certain things must be
escaped.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;ve covered a few of the DSLs that will be encountered when writing Rust code.
Some other DSLs we haven&#x27;t covered are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;macros&lt;&#x2F;strong&gt;: declarative macros are themselves a DSL. And procedural macros use
the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;syn&#x2F;0.15.26&#x2F;syn&#x2F;&quot;&gt;syn&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;quote&#x2F;0.6.11&#x2F;quote&#x2F;&quot;&gt;quote&lt;&#x2F;a&gt; crates to write valid rust code
inline.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;webassembly&lt;&#x2F;strong&gt;: &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;stdweb&#x2F;0.4.14&#x2F;stdweb&#x2F;macro.js.html&quot;&gt;stdweb&lt;&#x2F;a&gt;
(and soon also
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;wasm-bindgen&#x2F;0.2.37&#x2F;wasm_bindgen&#x2F;&quot;&gt;wasm-bindgen&lt;&#x2F;a&gt;) expose a
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;stdweb&#x2F;0.4.14&#x2F;stdweb&#x2F;macro.js.html&quot;&gt;&lt;code&gt;js!{}&lt;&#x2F;code&gt; macro&lt;&#x2F;a&gt;
to embed JavaScript code inside webassembly.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;routing:&lt;&#x2F;strong&gt; &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tide&#x2F;0.0.4&#x2F;tide&#x2F;&quot;&gt;tide&lt;&#x2F;a&gt; and other web frameworks
use a DSL to declare and match request URLs to handlers, and extract named
parameters in the process.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And there are many more examples used in other languages, such as embedding CSS,
SQL, shell scripts, shaders, meta programming and more.&lt;&#x2F;p&gt;
&lt;p&gt;I hope I&#x27;ve been able to highlight how common it is to use embedded DSLs in
Rust. In the next article we&#x27;ll take a closer look at some of the problems that
arise with embedded DSLs, and what we can do to mitigate this.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;2019-03-03-dsls-2&quot;&gt;&lt;em&gt;DSLs II: Challenges →&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Product Strategy</title>
            <pubDate>Fri, 15 Feb 2019 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/product-strategy/</link>
            <guid>https://blog.yoshuawuyts.com/product-strategy/</guid>
            <description>&lt;p&gt;I don&#x27;t like talking about business much. It kind of feels like a chore I&#x27;d
rather not have to deal with. But I do have to deal with it because I run my own
software consultancy.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve recently come across some interesting articles involving product strategy.
And I&#x27;ve been thinking about how they apply to the projects I build. I&#x27;ve found
that these are useful perspectives to consider when building products. Even if
it&#x27;s just to think about how others are strategizing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bundling-and-unbundling&quot;&gt;Bundling and Unbundling&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;There are only two ways to make money in business: One is to bundle; the
other is unbundle.&quot;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;em&gt;— &lt;a href=&quot;https:&#x2F;&#x2F;hbr.org&#x2F;2014&#x2F;06&#x2F;how-to-succeed-in-business-by-bundling-and-unbundling&quot;&gt;How to Succeed in Business by Bundling – and
Unbundling&lt;&#x2F;a&gt;
(2014)&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The way I like to think about it is that there&#x27;s value in producing parts so
people can acquire exactly the bits they want. And there&#x27;s value in assembling
parts into a cohesive whole and giving people a cohesive experience.&lt;&#x2F;p&gt;
&lt;p&gt;Like with every analogy, this is a simplification. But I think it&#x27;s a useful
lens to apply. When you&#x27;re building an (open source) project, are you bundling
or unbundling?&lt;&#x2F;p&gt;
&lt;p&gt;In my own work I&#x27;ve recently been doing a lot of work around both bundling and
unbundling. &lt;a href=&quot;http:&#x2F;&#x2F;choo.io&#x2F;&quot;&gt;Choo&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;choojs&#x2F;bankai&quot;&gt;Bankai&lt;&#x2F;a&gt;
and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-net-web&#x2F;tide&quot;&gt;Tide&lt;&#x2F;a&gt; are all examples of projects
where we bundle. The focus is on creating great user experiences, where all the
base wiring has already been taken care of for you.&lt;&#x2F;p&gt;
&lt;p&gt;On the other hand, the whole
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;search?q=org%3Achoojs+nano&amp;amp;unscoped_q=nano&quot;&gt;nano* suite&lt;&#x2F;a&gt; is
about creating parts that solve one problem well and can be assembled using only
the parts you need. This is valuable so people looking to build new experiences
don&#x27;t have to start from scratch, but can instead use the parts you&#x27;ve provided
-- and help improve those shared foundations in the process.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;commoditize-your-complement&quot;&gt;Commoditize Your Complement&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;A classic pattern in technology economics (...) is
layers of the stack attempting to become monopolies while turning other layers
into perfectly-competitive markets which are commoditized, in order to harvest
most of the consumer surplus; discussion and examples.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;em&gt;— &lt;a href=&quot;https:&#x2F;&#x2F;www.gwern.net&#x2F;Complement#2&quot;&gt;Commoditize Your Complement&lt;&#x2F;a&gt; (2018)&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I found out about this article in the wake of GitHub&#x27;s announcement to give
everyone free private repositories, where they used to cost a monthly fee.
People explained this as a move to curb competition. By preventing competitors
from taking people in by offering free private repos, GitHub can retain more
people on their platform, which in turn helps their business.&lt;&#x2F;p&gt;
&lt;p&gt;When applying this to more developer-focused projects (e.g. OSS), I can see this
being done by creating specs after products are done. For example Kubernetes
feels like it&#x27;s pulled this trick several times over. They needed a deployment
engine that could compete with AWS, so they took an internal project and
transformed it into a standard.&lt;&#x2F;p&gt;
&lt;p&gt;And when Kubernetes&#x27; relationship with Docker became contentious, they again
moved to replace Docker with &lt;a href=&quot;https:&#x2F;&#x2F;www.opencontainers.org&#x2F;&quot;&gt;a standard&lt;&#x2F;a&gt;,
causing Docker &lt;a href=&quot;https:&#x2F;&#x2F;mobyproject.org&#x2F;&quot;&gt;to get with the program&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t know if I like this approach much myself. It feels very much like
politics, and I don&#x27;t like those. But being able to identify when such
strategies are used seems like a useful skill to have.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping Up&lt;&#x2F;h2&gt;
&lt;p&gt;I hope this was somewhat interesting. I&#x27;ve been thinking about this quite a bit
recently, and found it to be useful. With a bit of luck it can be useful for you
too!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Rust 2019</title>
            <pubDate>Tue, 15 Jan 2019 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/rust-2019/</link>
            <guid>https://blog.yoshuawuyts.com/rust-2019/</guid>
            <description>&lt;p&gt;Hey everyone! Two days ago I released my &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;plans-for-2019&#x2F;&quot;&gt;plans for
2019&lt;&#x2F;a&gt;. Earlier today I wrote about
what I&#x27;d like to see for &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;wasm-2019&#x2F;&quot;&gt;Rust WASM in
2019&lt;&#x2F;a&gt;. This is my post about what I&#x27;d
like to see happen with Rust in 2019.&lt;&#x2F;p&gt;
&lt;p&gt;However unlike my two previous posts, I&#x27;d like to keep this one short and sweet.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;speaking-is-silver&quot;&gt;Speaking is silver&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;ve been drafting this post for the past two months. However none of it felt
right. I think it&#x27;s probably because others have put my feelings into words
better than I&#x27;m currently capable of. There are two posts I&#x27;d like you to read:&lt;&#x2F;p&gt;
&lt;p&gt;First off is &lt;a href=&quot;https:&#x2F;&#x2F;boats.gitlab.io&#x2F;blog&#x2F;post&#x2F;rust-2019&#x2F;&quot;&gt;Boats&#x27; post on organizational
debt&lt;&#x2F;a&gt;. It touches on how we
organize ourselves, and the problems we&#x27;re facing. I feel it distills so well
which challenges we face as an organization, and feel it ought to set the tone
on what to prioritize in this year&#x27;s roadmap.&lt;&#x2F;p&gt;
&lt;p&gt;The second post is &lt;a href=&quot;https:&#x2F;&#x2F;mgattozzi.com&#x2F;rust-in-2019-the-next-year-and-edition&#x2F;&quot;&gt;Gattozzi&#x27;s
post&lt;&#x2F;a&gt;. It feels
very personal and it&#x27;s focused around his experiences with the people in Rust.
I recognize myself a lot in those experiences. The community is changing, and
we&#x27;ll have to think of how we plan to change with it.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Have you read the two posts above? Yes? Great! Thank you for your time. From
here on out it&#x27;s desserts only.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;no-silos-no-heroes&quot;&gt;No silos, no heroes&lt;&#x2F;h3&gt;
&lt;p&gt;My main joy in programming stems from curiosity. I love learning new things,
figuring out how things work, and trying to improve them. The more open systems
are, the better this works. Which is why I got involved with open source in the
first place, and Rust with its RFC process later on.&lt;&#x2F;p&gt;
&lt;p&gt;However this becomes harder when systems are closed. When decision making is
opaque, code is hard to understand, or people use their status to justify
their actions. Every community has to deal with this, and Rust is no different.&lt;&#x2F;p&gt;
&lt;p&gt;I encourage everyone to reflect on who they look up to, and why. Which pieces of
code we think are cool, but don&#x27;t understand. Which crucial projects are lead by
people, not teams. We should think about what kind of community we want to be,
and how we can ensure we can get there, together.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;inclusive-behavior&quot;&gt;Inclusive behavior&lt;&#x2F;h3&gt;
&lt;p&gt;I often think about &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;aurynn&#x2F;status&#x2F;1062848550197911553&quot;&gt;this
tweet&lt;&#x2F;a&gt; by Aurynn:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Diversity is an emergent effect of inclusive behaviour.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I&#x27;d describe &quot;inclusive behaviour&quot; as behaviour that makes people feel valued,
welcome, and not threatened. Perhaps even simpler: behaviour that doesn&#x27;t
actively exclude people (&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Paradox_of_tolerance&quot;&gt;except people that exclude
others&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;I know we&#x27;d all like to believe the Rust community is a shining example of what
a programming community should look like. But have we truly reached the pinnacle
of behavior. Is there collectively no more room for improvement?&lt;&#x2F;p&gt;
&lt;p&gt;This definitely ties back into the two posts I linked to at the start of this
post. But instead of proposing directions for the core team to take: I&#x27;d like
this to be a call for each of us to reflect on how we interact with other
people.&lt;&#x2F;p&gt;
&lt;p&gt;Being welcoming is our collective responsibility. The way we behave reflects on
our peers. And the way our peers behave is a reflection of us.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping Up&lt;&#x2F;h2&gt;
&lt;p&gt;And that&#x27;s it for this year! I hope this has been useful! I&#x27;m starting to get a
taste for writing posts, so perhaps I&#x27;ll write about more things going forward.
But anyway, it&#x27;s late here, so I&#x27;m going to call it a night for now.&lt;&#x2F;p&gt;
&lt;p&gt;Hope you&#x27;re well &#x2F; have a good eve!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>WASM 2019</title>
            <pubDate>Tue, 15 Jan 2019 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/wasm-2019/</link>
            <guid>https://blog.yoshuawuyts.com/wasm-2019/</guid>
            <description>&lt;p&gt;Two days ago I wrote about &lt;a href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;plans-for-2019&#x2F;&quot;&gt;what I plan to work on this
year&lt;&#x2F;a&gt;.
This is my post about what I&#x27;d like to see happen with &lt;a href=&quot;https:&#x2F;&#x2F;rustwasm.github.io&#x2F;2018&#x2F;12&#x2F;06&#x2F;reflecting-on-rust-and-wasm-in-2018.html#rustwasm2019&quot;&gt;WebAssembly and Rust in
2019&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;status-quo&quot;&gt;Status quo&lt;&#x2F;h2&gt;
&lt;p&gt;2018 has been a really cool year for WASM and Rust. Back in February the
WASM toolchain became usable. Around the same time both
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustwasm&#x2F;wasm-bindgen&quot;&gt;wasm-bindgen&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustwasm&#x2F;wasm-pack&quot;&gt;wasm-pack&lt;&#x2F;a&gt; were kicked off (I remember
the dates because of &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;browserify&#x2F;rustify&quot;&gt;this gem&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;I think it&#x27;s interesting to point this out, because it means that at the time of
writing Rust&#x27;s defacto WASM toolchain is about 9 months old. That&#x27;s not a long
time for a project that is now considered standard. It&#x27;s super impressive how
much the WASM WG has accomplished last year!&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s take a look at what might be possible to accomplish this year.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fn-main&quot;&gt;fn main&lt;&#x2F;h2&gt;
&lt;p&gt;The narrative of the WASM WG&#x27;s tooling in 2018 has mostly revolved around
allowing people building browser applications to gradually introduce Rust into
their workflows. This has been great for people looking to improve parts of
their existing JavaScript codebase.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;d like Rust&#x27;s WASM story to focus on building an integrated experience this
year. Even though WASM is not intended to replace JavaScript, I think we can
learn a lot by pushing WASM as far as we can by itself. I think this should give
us insights in what is missing, and what needs improving, leading us to create a
better Rust WASM experience for &lt;em&gt;every&lt;&#x2F;em&gt; workflow.&lt;&#x2F;p&gt;
&lt;p&gt;I think a good goal is to aim to add first-class support for standalone WASM
binaries. Standalone meaning: the Rust code drives the application logic, rather
than having JavaScript call into Rust library functions.&lt;&#x2F;p&gt;
&lt;p&gt;For example
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustwasm&#x2F;wasm-bindgen&#x2F;pull&#x2F;1057&quot;&gt;&lt;code&gt;[wasm_bindgen(start)]&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
can be used as an application entry point, and the resulting binaries can be
served with a static web server. But neither of them feel as nice as Rust&#x27;s own
&lt;code&gt;fn main&lt;&#x2F;code&gt; and &lt;code&gt;cargo run&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;build-an-ecosystem&quot;&gt;Build an ecosystem&lt;&#x2F;h2&gt;
&lt;p&gt;Speaking of ecosystems, we should probably build one! There&#x27;s a few points I
think are important:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Don&#x27;t create branded silos.&lt;&#x2F;strong&gt; Branding might perhaps be useful to achieve
fame. But if we truly want Rust&#x27;s WASM story to succeed we should
think of ways to collaborate instead of carving out territory.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Centralize discovery.&lt;&#x2F;strong&gt; We&#x27;re trying to build an ecosystem from scratch.
Having a place where module authors can share their results will likely allow
us to coordinate without much overhead. Something that for example might work
is for the WASM WG to create an
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sindresorhus&#x2F;awesome&#x2F;blob&#x2F;master&#x2F;awesome.md&quot;&gt;awesome&lt;&#x2F;a&gt;
list under the GitHub org, and liberally accepting contributions.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Encourage experimentation.&lt;&#x2F;strong&gt; I think it&#x27;s way too early in Rust&#x27;s lifecycle
to know what the right way is to do things. Even more so for Rust WASM. I
think we should encourage experimentation and sharing results early. The
lower we can make the boundary to experiment, the likelier it is that people
will get involved, and in turn the likelier the ecosystem will grow in both
size and quality.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;keep-polishing&quot;&gt;Keep polishing&lt;&#x2F;h2&gt;
&lt;p&gt;This is the &quot;miscellaneous&quot; part of my post. There&#x27;s some things I&#x27;ve noticed
that are missing, or I wish we had in no particular order:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;wasm-bindgen&lt;&#x2F;code&gt; doesn&#x27;t generate source maps yet. Having them would be
excellent for debugging.&lt;&#x2F;li&gt;
&lt;li&gt;The story around async and WASM seems only partly executed so far. Rust
Futures can be converted to JS Promises and hooked into the JS event loop, but
running your own multi-threaded loop seems to involve a lot of manual work
still.&lt;&#x2F;li&gt;
&lt;li&gt;Rust WASM artifacts are single binaries which are hard to cache and
incrementally load. There&#x27;s probably exploration possible around code
splitting and dynamically loading.&lt;&#x2F;li&gt;
&lt;li&gt;Setting up a WASM project requires &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustwasm&#x2F;rust-webpack-template&#x2F;blob&#x2F;7ff65a1a463a770a5ed3c370c114a59a7629cb86&#x2F;crate&#x2F;src&#x2F;lib.rs#L8-L28&quot;&gt;quite some
boilerplate&lt;&#x2F;a&gt;.
It&#x27;d be nice if we could find ways to reduce this.&lt;&#x2F;li&gt;
&lt;li&gt;Passing errors to and from JS &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustwasm&#x2F;wasm-bindgen&#x2F;issues&#x2F;1017&quot;&gt;isn&#x27;t as smooth as it could
be&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;&#x2F;h2&gt;
&lt;p&gt;And that&#x27;s more or less what I&#x27;d like to see from Rust WASM this year. I feel
Rust&#x27;s WASM story is very much on the right patch already, and I hope this will
only keep improving in 2019.&lt;&#x2F;p&gt;
&lt;p&gt;I hope this has been useful. Thanks for reading!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>Plans for 2019</title>
            <pubDate>Sun, 13 Jan 2019 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/plans-for-2019/</link>
            <guid>https://blog.yoshuawuyts.com/plans-for-2019/</guid>
            <description>&lt;p&gt;Last year was pretty good. I worked on &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;choojs&#x2F;&quot;&gt;choo&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;datrs&quot;&gt;datrs&lt;&#x2F;a&gt;, and got 2 cats. I started working out (more)
regularly, and towards the end of the year even consistently stayed on top of my
email. Also I&#x27;ve cooked a ton of food, and definitely feel like I&#x27;m a better
cook than I was at the start of the year.&lt;&#x2F;p&gt;
&lt;p&gt;In this post I want to share my plans &amp;amp; goals for this year.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;no-more-injuries&quot;&gt;No more injuries&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;ve had problems with my wrists since I was about 16 years old. This has mostly
been due to bad posture while using laptops, and working too long and too hard.
Last year it never got so bad I couldn&#x27;t work, but I&#x27;m definitely not healed
yet.&lt;&#x2F;p&gt;
&lt;p&gt;This year I&#x27;d like to continue working towards making a full recovery. This
means probably working less long hours, taking more breaks, and not working on
weekends. Also paying more attention to my &lt;a href=&quot;http:&#x2F;&#x2F;www.workrave.org&#x2F;&quot;&gt;workrave&lt;&#x2F;a&gt;
timers.&lt;&#x2F;p&gt;
&lt;p&gt;Being better about timing work is a good idea by itself. But having a goal
motivating is the little extra nudge that really makes me want to commit to
this.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;p2p&quot;&gt;p2p&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;datrs.yoshuawuyts.com&#x2F;&quot;&gt;datrs&lt;&#x2F;a&gt; has been really fun to work on last
year. It was my first full-time Rust job, and I&#x27;m really pleased with the
results. This year I&#x27;d like to get the networking stack going, based on
async&#x2F;await and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;withoutboats&#x2F;romio&quot;&gt;romio&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s is useful for many reasons, but in particular I&#x27;m excited for the
possibility of helping the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;peermaps&#x2F;eyros&quot;&gt;peermaps&lt;&#x2F;a&gt;
advance. Emphasis on &quot;possibility&quot;. Regardless  going to be useful to provide
feedback on async&#x2F;await by building out more networking implementations outside
exclusively HTTP contexts.&lt;&#x2F;p&gt;
&lt;p&gt;I hope to have time to work this in Q2&#x2F;Q3 this year, on the side. However if
you&#x27;d like to get involved to help it advance more actively I&#x27;d be more than
happy to take a more managerial role and help people move in the right
direction!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;web-services&quot;&gt;Web Services&lt;&#x2F;h2&gt;
&lt;p&gt;Because Rust&#x27;s async&#x2F;await story isn&#x27;t stabilized yet, the ecosystem on top of
it still needs a lot of work. This year I&#x27;ll be working on building out modules
that work on on top of async Rust.&lt;&#x2F;p&gt;
&lt;p&gt;On the one hand there&#x27;s a ton of protocol work that&#x27;s in various stages of
completion. HTTP&#x2F;2, SSE, HTTP&#x2F;3 crates exist, but they don&#x27;t feel quite as
polished as stdlib&#x27;s TCP interface. We should probably have support for these,
which we can likely get in the near term by wrapping existing C libraries.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s also the higher-level web-app stories. It don&#x27;t feel like we have a good
story yet for generating REST docs, reusable middleware, and authentication. I
feel there&#x27;s a lot of room to experiment and improve this space!&lt;&#x2F;p&gt;
&lt;p&gt;I think it&#x27;d be great if we could tackle these problems with the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-net-web&quot;&gt;rust-net-web
WG&lt;&#x2F;a&gt;. But this requires us to become better at
organizing. Which is why I think this is a good opportunity to become more
involved, and help guide this along!&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve already started working on this, and plan to continue on it for the
foreseeable future!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;frontend&quot;&gt;Frontend&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;m very curious if Rust can help us build better interfaces on the Web. To me
it&#x27;s clear that it has potential, but it&#x27;s not clear yet what the abstractions
should look like.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;d love to contribute this year to the Rust WASM by leveraging my knowledge of
building &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;choojs&#x2F;&quot;&gt;choo&lt;&#x2F;a&gt;, and helping the ecosystem succeed.
I&#x27;ve already started joining the WASM WG meetings, and plan to become more
involved as the year goes on.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;relationship&quot;&gt;Relationship&lt;&#x2F;h2&gt;
&lt;p&gt;My partner is more concensious than I am, and that&#x27;s sometimes hard in our
relationship. Especially when it comes to doing chores around the house, I&#x27;m
usually less organized about most things. (Except the kitchen. I run a tight
ship.)&lt;&#x2F;p&gt;
&lt;p&gt;I want to be better at managing the cat, the house, and the other cat this year.
Also be better about planning trips and weekend plans. I feel we&#x27;re not
exceptionally out of balance, but it&#x27;s clear that there&#x27;s room to do better.
So I should take this as a chance to learn and improve.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;content&quot;&gt;Content&lt;&#x2F;h2&gt;
&lt;p&gt;I want to become better at producing content also. Write more often, and become
increasingly clear. When I do video streams, have a plan and curate the output
better. Make it feel like the things I make are recognizable.&lt;&#x2F;p&gt;
&lt;p&gt;I haven&#x27;t cared about this much in the past; but I think paying a bit more
attention to production quality is another way of improving at communication.
And that seems like something worth investing in.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping Up&lt;&#x2F;h2&gt;
&lt;p&gt;And that&#x27;s in broad strokes what I was thinking of working on this year. I don&#x27;t
think they&#x27;re spectacular plans. But I feel they&#x27;re achievable. And I&#x27;m pretty
excited to make them happen this year!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>A New Blog</title>
            <pubDate>Sun, 30 Dec 2018 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/a-new-blog/</link>
            <guid>https://blog.yoshuawuyts.com/a-new-blog/</guid>
            <description>&lt;p&gt;Hey everyone! Welcome to my new blog. Stretch your legs. Make yourself at home.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why&quot;&gt;Why?&lt;&#x2F;h2&gt;
&lt;p&gt;I used to be quite active on &lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@yoshuawuyts&quot;&gt;Medium.com&lt;&#x2F;a&gt;, but
I don&#x27;t think the site has been changing for the better, and want to try
something new. Something that&#x27;s my own. Something where I have the creative
freedom to structure it however I like.&lt;&#x2F;p&gt;
&lt;p&gt;So this is it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;is-this-a-dat-site&quot;&gt;Is this a dat:&#x2F;&#x2F; site?&lt;&#x2F;h2&gt;
&lt;p&gt;It&#x27;s not. At least: not yet. Perhaps we&#x27;ll get there eventually, but for now I&#x27;m
happy to build a static site, and distribute it from my own server. I&#x27;ve always
wanted to be better at managing servers, and this is a fun addition to my
growing collection of things running on a single 5&#x2F;euro month instance. Keeping
things static means performance is reliable, and reliability is nice for hobby
projects.&lt;&#x2F;p&gt;
&lt;p&gt;A long story short: perhaps I&#x27;ll make the jump to dat:&#x2F;&#x2F; eventually. But not
right now.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;source&quot;&gt;Source&lt;&#x2F;h2&gt;
&lt;p&gt;You can find the source on
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yoshuawuyts&#x2F;blog&quot;&gt;github.com&#x2F;yoshuawuyts&#x2F;blog&lt;&#x2F;a&gt;, and the
server configuration on
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yoshuawuyts&#x2F;server&quot;&gt;github.com&#x2F;yoshuawuyts&#x2F;server&lt;&#x2F;a&gt;. The
theme is &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;getzola&#x2F;after-dark&quot;&gt;Zola After Dark&lt;&#x2F;a&gt;, but I expect
it won&#x27;t be long before I start tinkering with it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping Up&lt;&#x2F;h2&gt;
&lt;p&gt;Thanks for reading! I hope you visit again soon!&lt;&#x2F;p&gt;
</description>
        </item>
        <item>
            <title>pull streams</title>
            <pubDate>Mon, 21 Mar 2016 00:00:00 +0000</pubDate>
            <link>https://blog.yoshuawuyts.com/pull-streams/</link>
            <guid>https://blog.yoshuawuyts.com/pull-streams/</guid>
            <description>&lt;p&gt;&lt;em&gt;This post is part of a series:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Pull Streams (current)&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;rust-streams&quot;&gt;&lt;em&gt;Rust Streams&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Streams are an asynchronous abstraction that allows dealing with large data sets
in small chunks, pushing bottlenecks into the IO layer. This usually leads to less
memory cost and increased performance, which is a &lt;em&gt;very&lt;&#x2F;em&gt; good thing.&lt;&#x2F;p&gt;
&lt;p&gt;In streams, data flows from a Source, through a bunch of Through streams, into
a Sink:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;  ┌────────┐   ┌─────────┐   ┌────────┐
&lt;&#x2F;span&gt;&lt;span&gt;  │ Source │──▶│ Through │──▶│  Sink  │
&lt;&#x2F;span&gt;&lt;span&gt;  └────────┘   └─────────┘   └────────┘
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Node has shipped streams as part of its standard library since its early days.
However with each release, new features, APIs and concepts were added, making
the current implementation very unwieldy. In my years as a Node developer I&#x27;ve
only met a handful of developers that felt comfortable using the current
version of Node streams. In an ideal world streams would be used as much in
Node as pipes are used in shell.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;enter-pull-streams&quot;&gt;Enter pull-streams&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dominictarr&#x2F;pull-stream&quot;&gt;pull-stream&lt;&#x2F;a&gt; is an alternative
model for streams created by &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dominictarr&quot;&gt;Dominic Tarr&lt;&#x2F;a&gt;.
Like Node streams, it has a concept of &lt;em&gt;backpressure&lt;&#x2F;em&gt;. This means that instead
of a source pushing out data as fast as it can, the consumer stream &lt;em&gt;pulls&lt;&#x2F;em&gt;
data once it&#x27;s ready to handle more. This leads to a program never holding more
data in memory than it needs.&lt;&#x2F;p&gt;
&lt;p&gt;The Node streams source is well over 1200 lines, without even accounting for
dependencies. The &lt;code&gt;pull-stream&lt;&#x2F;code&gt; source is just 28 lines, which is a whopping
&lt;code&gt;0.4kb&lt;&#x2F;code&gt; minified:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span&gt;module.exports = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;function &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;pull &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(typeof &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;a &lt;&#x2F;span&gt;&lt;span&gt;=== &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39; &amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;.length === &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return function &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;var &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;args &lt;&#x2F;span&gt;&lt;span&gt;= [].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;slice&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;call&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;arguments&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;pull&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;apply&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;null&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;args&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;var &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;read &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;a
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;var &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;n &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;arguments&lt;&#x2F;span&gt;&lt;span&gt;.length
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;var &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;i &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;read &lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&amp;amp; typeof &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;.source === &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;read &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;.source
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;i &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;++) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;var &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;s &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;arguments&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(typeof &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;s &lt;&#x2F;span&gt;&lt;span&gt;=== &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;) {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;read &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;s &lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&amp;amp; typeof &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;s &lt;&#x2F;span&gt;&lt;span&gt;=== &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;) {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;sink&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;read &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;.source
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;read
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Don’t be fooled by the simple exterior though, &lt;code&gt;pull-stream&lt;&#x2F;code&gt; provides the same
functionality as Node streams do. With fewer lines of code there’ll be less
bugs, and room to optimize every last bit of code.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pull-stream-types&quot;&gt;Pull-stream types&lt;&#x2F;h2&gt;
&lt;p&gt;In pull-streams there are 3 types of streams: source, through and sink. In
order to let data flow, a source and sink must be connected. Through streams
are combinations of sources and sinks, making every connection in the pipeline
a source and a sink that talk to each other. Conceptually it looks like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;  ┌──────┐   ┌──────┐   ┌──────┐   ┌──────┐
&lt;&#x2F;span&gt;&lt;span&gt;  │Source│──▶│ Sink │ ┌▶│ Sink │ ┌▶│ Sink │
&lt;&#x2F;span&gt;&lt;span&gt;  └──────┘   ├──────┤ │ ├──────┤ │ └──────┘
&lt;&#x2F;span&gt;&lt;span&gt;             │Source│─┘ │Source│─┘
&lt;&#x2F;span&gt;&lt;span&gt;             └──────┘   └──────┘
&lt;&#x2F;span&gt;&lt;span&gt;              Through    Through
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If a source and a through stream are connected they will not start emitting
data until a sink is attached at the end. Likewise, if a through and sink are
connected, they will not start flowing data until a source is attached at the
start. This allows composition of arbitrary streams into pipelines similar to
what &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mafintosh&#x2F;pumpify&quot;&gt;pumpify&lt;&#x2F;a&gt; provides for Node streams.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;composition&quot;&gt;Composition&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;pull-stream&lt;&#x2F;code&gt;s use the &lt;code&gt;pull()&lt;&#x2F;code&gt; function to combine sinks and sources. Because
sinks connect to sources, any number of streams can be connected. It&#x27;s
functional composition all the way.&lt;&#x2F;p&gt;
&lt;p&gt;Duplex (through) streams are objects that have a &lt;code&gt;.source&lt;&#x2F;code&gt; and &lt;code&gt;.sink&lt;&#x2F;code&gt; properties
on them. The following three methods of connecting &lt;code&gt;pull-stream&lt;&#x2F;code&gt;s are equivalent:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;pull&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;.source, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;sink&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;pull&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;.source, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;sink&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;sink&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;.source)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;sink&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;.source)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;pull&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;helper-functions&quot;&gt;Helper functions&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;pull-stream&lt;&#x2F;code&gt; ships with helper functions such as &lt;code&gt;asyncMap&lt;&#x2F;code&gt; that make common
interactions trivial. See the docs for available
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dominictarr&#x2F;pull-stream&#x2F;blob&#x2F;master&#x2F;docs&#x2F;sources.md&quot;&gt;sources&lt;&#x2F;a&gt;,
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dominictarr&#x2F;pull-stream&#x2F;blob&#x2F;master&#x2F;docs&#x2F;sinks.md&quot;&gt;sinks&lt;&#x2F;a&gt;
and
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dominictarr&#x2F;pull-stream&#x2F;blob&#x2F;master&#x2F;docs&#x2F;throughs.md&quot;&gt;throughs&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s create a basic map-reduce pipeline using &lt;code&gt;asyncMap&lt;&#x2F;code&gt; where we
asynchronously &lt;code&gt;fs.stat&lt;&#x2F;code&gt; an array of files, and gather the results in an array:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;pull &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;require&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;pull&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fs &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;require&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;source &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;pull&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;values&lt;&#x2F;span&gt;&lt;span&gt;([ &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;.&#x2F;file1&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;, &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;.&#x2F;file2&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;, &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;.&#x2F;file3&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39; ])
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;through &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;pull&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;asyncMap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;stat&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;sink &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;pull&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;function &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;err&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;err&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;err&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;})
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;pull&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;source&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;through&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;sink&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Because under the hood we&#x27;re just composing functions, the overhead of doing
this is reduced to a bare minimum.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;error-handling&quot;&gt;Error handling&lt;&#x2F;h2&gt;
&lt;p&gt;In Node streams errors don&#x27;t propagate through &lt;code&gt;.pipe()&lt;&#x2F;code&gt; chains. It&#x27;s therefore
common practice to either use helper libraries or attach a &lt;code&gt;.on(&#x27;error&#x27;)&lt;&#x2F;code&gt;
listener to every stream. Getting errors wrong is not a great feeling.&lt;&#x2F;p&gt;
&lt;p&gt;In &lt;code&gt;pull-stream&lt;&#x2F;code&gt;s errors are passed into the callback, which grinds the whole
stream pipeline to a halt. It&#x27;s again the familiar API of &lt;code&gt;cb(err)&lt;&#x2F;code&gt; for an
error and &lt;code&gt;cb(null, value)&lt;&#x2F;code&gt; for success.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s a source stream that returns a single &lt;code&gt;fs.stat&lt;&#x2F;code&gt; value:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fs &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;require&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;function &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;readFile &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;filename&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;var &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;read &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; keep track if we&amp;#39;ve executed the action
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return function &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;source &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;end&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cb&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;end&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;cb&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;end&lt;&#x2F;span&gt;&lt;span&gt;)     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; stop signal was passed, stop doing things
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;cb&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;)   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; we&amp;#39;re done with fs.stat, stop doing things
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;stat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;filename&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;function &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;err&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;file&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;err&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;cb&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;err&lt;&#x2F;span&gt;&lt;span&gt;)   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; ohey, an error
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;read &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true               &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; mark that we&amp;#39;ve executed the action
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;cb&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;null&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;file&lt;&#x2F;span&gt;&lt;span&gt;)     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; pass value down the pipeline
&lt;&#x2F;span&gt;&lt;span&gt;    })
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;wrapping-it-up&quot;&gt;Wrapping it up&lt;&#x2F;h2&gt;
&lt;p&gt;And that&#x27;s it. I could keep whipping out &lt;code&gt;pull-stream&lt;&#x2F;code&gt; examples, but I think
we&#x27;ve made our point: streams are a cool idea; &lt;code&gt;pull-stream&lt;&#x2F;code&gt; is a neat
implementation. If you&#x27;re keen to learn more, take a look at the links below.
I hope this was useful; give &lt;code&gt;pull-stream&lt;&#x2F;code&gt; a try let me know how you go! -Yosh&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;yoshuawuyts&quot;&gt;twitter&#x2F;yoshuawuyts&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yoshuawuyts&quot;&gt;github&#x2F;yoshuawuyts&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;see-also&quot;&gt;See Also&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dominictarr&#x2F;pull-stream&quot;&gt;pull-stream&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dominictarr&#x2F;pull-stream-examples&quot;&gt;pull-stream-examples&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dominictarr&#x2F;pull-stream&#x2F;blob&#x2F;master&#x2F;spec.md&quot;&gt;pull-stream&#x2F;spec&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dominictarr&#x2F;pull-stream&#x2F;blob&#x2F;master&#x2F;docs&#x2F;sources.md&quot;&gt;pull-stream&#x2F;sources&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dominictarr&#x2F;pull-stream&#x2F;blob&#x2F;master&#x2F;docs&#x2F;sinks.md&quot;&gt;pull-stream&#x2F;sinks&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dominictarr&#x2F;pull-stream&#x2F;blob&#x2F;master&#x2F;docs&#x2F;throughs.md&quot;&gt;pull-stream&#x2F;throughs&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
        </item>
    </channel>
</rss>
